陈天平--第二次作业
这个作业属于哪个课程 | 至诚软工实践F班 |
---|---|
这个作业要求在哪里 | 第二次作业-个人编程 |
这个作业的目标 | 数据、接口抓取;版本控制 |
Github 地址 | GitHub地址 |
part01
使用 fiddler 抓包工具+代码,实时监控朴朴上某产品的详细价格信息。
思考
- 爬取数据,需要接口,获取接口使用fiddler,拿到接口,编写程序,
步骤
- 抓取接口
准备: 安装并配置fiddler
开始:
测试接口:
分析数据:
在线解析json
-
编写程序
准备:开发平台 idea,语言:Java (api),jdk版本 1.8
开始:
-
获取响应目标商品数据:需要发送一个请求来获取响应的内容
Utils的sendGet()实现了这一需求
注释掉的是原始请求头的内容(微信小程序)
/** * 功能:发送GET请求,获取响应体 * @param _url 请求URL * @return 响应体 */ public String sendGet(String _url) throws IOException { URL url = new URL(_url); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // connection.setRequestProperty("Host","j1.pupuapi.com"); // connection.setRequestProperty("Connection","keep-alive"); // connection.setRequestProperty("Accept","application/json"); connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat"); // connection.setRequestProperty("content-type","application/json"); // connection.setRequestProperty("open-id","oMwzt0HELosalSPJfmKq2cifPTAk"); // connection.setRequestProperty("pp-os","0"); // connection.setRequestProperty("pp-placeid","227bd5f1-40d5-4bdf-b5c2-2e091a512c9d"); // connection.setRequestProperty("pp-version","2021063100"); // connection.setRequestProperty("pp_storeid","7c1208da-907a-4391-9901-35a60096a3f9"); // connection.setRequestProperty("Referer","https://servicewechat.com/wx122ef876a7132eb4/156/page-frame.html"); // connection.setRequestProperty("Accept-Encoding","gzip, deflate, br"); // connection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.9,en;q=0.8"); connection.connect(); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)); StringBuilder result = new StringBuilder(); String lines; while ((lines = reader.readLine()) != null) { lines = new String(lines.getBytes(), StandardCharsets.UTF_8); result.append(lines).append("\n"); } reader.close(); connection.disconnect(); return result.toString(); }
【注意】如果放开以下代码,控制台输出乱码(请求编码问题)
// connection.setRequestProperty("Accept-Encoding","gzip, deflate, br");
-
数据处理
响应信息
JSONObject.parseObject(new Utils().sendGet(url));
商品JSON数据
JSONObject data = jsonObject.getJSONObject("data");
商品名
data.get("name")
折后价
data.get("price")
原价
data.get("market_price")
Main 主类
getGoodsData概要
/** * 功能:获取商品信息 * @param url 商品地址 * @return 返回商品信息 * */ public String getGoodsData(String url) throws IOException { StringBuilder sb = new StringBuilder(); Main main = new Main(); // 数据转json格式 JSONObject jsonObject = JSONObject.parseObject(new Utils().sendGet(url)); // 得到data部分 JSONObject data1 = jsonObject.getJSONObject("data"); // 添加关键信息 到 sb ... sb.append("价格:").append(main.stringToDouble(data1.get("price").toString())).append("\n"); ... return sb.toString(); }
getPrice 返回的数据中,商品的价格是实际的100倍(即没有小数),展示时需要转换成小数
/** * 功能:获取商品价格 * @param priceStr 目标商品的数据字符串 * @return 双精度商品价格 * */ public double getPrice(String priceStr){ // 转json 并 得到data部分 return Double.parseDouble(JSONObject.parseObject(priceStr).getJSONObject("data").get("price").toString())/100; }
实时查看价格实现
线程在后台线程中调度,设置为定期重复执行。(注意访问太频繁会被封ip)
/** * 功能:展示价格波动 * @param url 指定访问url * @param time 访问间隔时长(单位:秒) * */ public void displayPrice(String url, int time){ Timer timer = new Timer(); // 定时任务 timer.schedule(new TimerTask(){ @Override public void run() { try{ double price = new Main().getPrice(new Utils().sendGet(url)); System.out.println("当前时间为:" + getLocalTime() + ",价格为:" + price); }catch (Exception e){ e.printStackTrace(); } } },0,time*1000); }
? 运行结果:
?
? 需要优化的地方:功能函数不输出信息等
? 该优化在第二次提交部分实现
-
-
上传到GitHub仓库
- GitHub截图
-
遇到问题与解决方案
csdn
part02
爬取自己的知乎收藏夹,以每个收藏夹的名称为大类,其下展示各个具体收藏文章的名称及其链接。
思考
- 跟part01差不多,不同的就是处理数据和数据展示
步骤
-
使用fidder得到的接口
https://www.zhihu.com/api/v4/people/zhi-hu-yong-hu-2021-36/collections
-
获取收藏夹id集合
/** * 功能:获取收藏夹id * @param url 收藏夹 * @return 收藏夹id列表 * */ public ArrayList
getPackageId(String url) throws IOException { Utils utils = new Utils(); JSONObject jsonObject = JSONObject.parseObject(utils.sendGet(url)); JSONArray data = JSONArray.parseArray(jsonObject.get("data").toString()); System.out.println("该用户共有" + data.size() + "个收藏夹"); ArrayList arrayList = new ArrayList<>();// 收藏夹id 方便后续请求收藏夹下的文章 for (Object datum : data) { // 转换 JSONObject temp = JSONObject.parseObject(datum.toString()); System.out.println("title: " + temp.get("title") + " , description: " + temp.get("description") + " , url: " + temp.get("url")); // 记录收藏夹id arrayList.add(temp.get("id").toString()); } return arrayList; } -
输出所有收藏夹包含的文章信息
/** * 功能:输出文章信息 * @param packageId 收藏夹id列表 * */ public void displayData(ArrayList
packageId) throws IOException { // 接口格式 https://www.zhihu.com/api/v4/collections/xxxxx/items?offset=0&limit=20 其中xxxxx为收藏夹id Utils utils = new Utils(); System.out.println("----------------------------------------------------------------------------"); for (Object id : packageId) { String _url = "https://www.zhihu.com/api/v4/collections/" + id + "/items?offset=0&limit=20"; // 查看数据 JSONObject object = JSONObject.parseObject(utils.sendGet(_url)); JSONArray data1 = JSONObject.parseArray((object.get("data").toString()));// 单篇文章内容对象 每个对象5个Object for (Object o : data1) { JSONObject temp = JSONObject.parseObject(o.toString()); JSONObject content = JSONObject.parseObject(temp.get("content").toString());// 单篇文章内容 JSONObject question = JSONObject.parseObject(content.get("question").toString());// 问题对象 String title = question.get("title").toString();// 问题 String excerpt = content.get("excerpt").toString();// 回答 String mk_content = content.get("content").toString();// Markdown格式问题,获取图片地址 if (mk_content.indexOf(" -
运行结果
sendGet等其他步骤与part01相似