IT评测·应用市场-qidao123.com
标题:
(Java)记一次通过API递归分页“爬取”网页数据的开发经历
[打印本页]
作者:
盛世宏图
时间:
2023-5-30 10:33
标题:
(Java)记一次通过API递归分页“爬取”网页数据的开发经历
前言
在最近的互联网项目开发中,需要获取用户的访问ip信息进行统计的需求,用户的访问方式可能会从微信内置浏览器、Windows浏览器等方式对产品进行访问。
当然,获取这些关于ip的信息是合法的。但是,这些ip信息我们采用了其它第三方的服务来记录,并不在我们的数据库中。
这些ip信息是分组存放的,且每个分组都都是分页(1页10条)存放的,如果一次性访问大量的数据,API很有可能会报错。
怎样通过HTTP的方式去获取到信息,并且模拟浏览器每页每页获取10条的信息,且持久到数据库中,就成了当下亟需解决的问题。
通过以上的分析,可以有大致以下思路:
1、拿到该网页http请求的url地址,同时获取到调用该网页信息的参数(如:header、param等);
2、针对分页参数进行设计,由于需要不断地访问同一个接口,所以可以用循环+递归的方式来调用;
3、将http接口的信息进行解析,同时保证一定的访问频率(大部分外部http请求都会有访问频率限制)让返回的数据准确;
4、整理和转化数据,按照一定的条件,批量持久化到数据库中。
一、模拟http请求
我们除了在项目自己写API接口提供服务访问外,很多时候也会使用到外部服务的API接口,通过调用这些API来返回我们需要的数据。
如:
钉钉开放平台https://open.dingtalk.com/document/orgapp/user-information-creation、
微信开放平台https://open.weixin.qq.com/cgi-bin/index?t=home/index&lang=zh_CN等等进行开发。
这里分享一下从普通网页获取http接口url的方式,从而达到模拟http请求的效果:
以谷歌chrome浏览器为例,打开调式模式,根据下图步骤:
尤其注意使用Fetch/XHR,右键该url—>copy—>copy as cURL(bash):
随后粘贴到Postman中,模拟http请求:
粘贴的同时,还会自动带上header参数(以下这4个参数比较重要,尤其是cookie):
这样,就可以访问到所需的数据了,并且数据是json格式化的,这便于我们下一步的数据解析。
二、递归+循环设计
有几个要点需要注意:
1、分内外两层,内外都需要获取数据,即外层获取的数据是内层所需要的;
2、每页按照10条数据来返回,直到该请求没有数据,则访问下一个请求;
3、递归获取当前请求的数据,注意页数的增加和递归终止条件。
废话不多说,直接上代码:
点击查看代码[code]public boolean getIpPoolOriginLinksInfo(HashMap commonPageMap, HashMap headersMap,String charset){ //接口调用频率限制 check(commonAPICheckData); String linkUrl = "https://xxx.xxx.com/api/v1/xxx/xxx"; HashMap linkParamsMap = new HashMap(); linkParamsMap.put("page",commonPageMap.get("page")); linkParamsMap.put("size",commonPageMap.get("size")); String httpLinkResponse = null; //封装好的工具类,可以直接用apache的原生httpClient,也可以用Hutool的工具包 httpLinkResponse = IpPoolHttpUtils.doGet(linkUrl,linkParamsMap,headersMap,charset); JSONObject linkJson = null; JSONArray linkArray = null; linkJson = JSON.parseObject(httpLinkResponse).getJSONObject("data"); linkArray = linkJson.getJSONArray("resultList"); if (linkArray != null){ //递归计数 if (!commonPageMap.get("page").toString().equals("1")){ commonPageMap.put("page","1"); } // 每10条urlId,逐一遍历 for (Object linkObj : linkJson.getJSONArray("resultList")) { JSONObject info = JSON.parseObject(linkObj.toString()); String urlId = info.getString("urlId"); // 获取到的每个urlId,根据urlId去获取ip信息(即内层的业务逻辑,我这里忽略,本质就是拿这里的参数传到内层的方法中去) boolean flag = getIpPoolOriginRecords(urlId, commonPageMap, headersMap, charset); if (!flag){ break; } } Integer page = Integer.parseInt(linkParamsMap.get("page").toString()); if (page
欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/)
Powered by Discuz! X3.4