Java数据采集-7.Ajax无刷新请求(翻页-3)

来源:互联网 发布:ei数据库免费检索入口 编辑:程序博客网 时间:2024/06/01 09:07

本次抓取地址:http://www.iconfont.cn/
项目源码:https://github.com/geekfly2016/Spider
代码目录:Spider/src/xyz/geekfly/get_list/IconFont.Java

本篇继上述博客,介绍Ajax无刷新加载数据的方式,抓取阿里巴巴矢量图库。
技术重点:

  • HttpClient 模拟请求
  • FastJson 处理Json格式的数据

(由于此处需要模拟Post请求,并且包含请求头信息和参数,Jsoup已经无法满足需求,其主要适用于数据解析,故此代码使用HttpClient模拟请求)
上述技术请自行学习,此处指包括使用。
本代码以来多个Jar包,已更新在Lib中。
这里写图片描述

1.分析请求

打开目标网页,输入Java关键字,打开Chrome的开发者工具,点击页码,看到如下请求:
这里写图片描述


General中数据如下:

Request URL:http://www.iconfont.cn/api/icon/search.jsonRequest Method:POSTStatus Code:200 OKRemote Address:140.205.34.99:80Referrer Policy:no-referrer-when-downgrade

分析:
加载数据的Url为:http://www.iconfont.cn/api/icon/search.json
请求方式:Post


请求头(Request Header)中数据如下(Cookie数据过长,有删减):

Accept:application/json, text/javascript, */*; q=0.01Accept-Encoding:gzip, deflateAccept-Language:zh-CN,en-US;q=0.8,en;q=0.6,zh;q=0.4Connection:keep-aliveContent-Length:98Content-Type:application/x-www-form-urlencoded; charset=UTF-8Cookie:UM_distinctoDITjHost:www.iconfont.cnOrigin:http://www.iconfont.cnReferer:http://www.iconfont.cn/search/index?q=java&page=1User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36X-Requested-With:XMLHttpRequest

在模拟请求中,一般使用到的参数有:
Cookie,Host,Referer。
User-Agent就不用说了,这个是必须的。
所以下文代码中使用的参数,就是在浏览器里面直接拷贝的上述值。

  • 并不是所有的请求都需要加上述参数
  • 不同的网站也会有不同的参数
  • 有些动态的数据需要动态生成

和网站的安全机制有关,若发现请求获取不到数据,或返回错误的数据时,需考虑参数问题,先尝试把必须添加的参数加上,如果不行再继续添加其他参数,不断尝试可以获取正常的数据为止。
(个人比较懒,最开始不加参数,不能获取数据在添加,或者你也可以每个网站都加上所有的参数)


请求参数:

q:javasortType:updated_atpage:1pageSize:54t:1502713725794ctoken:bL67K02mQl16IlJizxgeicon-font

请求参数一般需要全部添加

  • 注意区分和请求头(Request Header)的区别
  • 注意请求参数是Json类型还是字典类型

2.编写请求函数

  • 创建HttpClient和HttpPost

    HttpClient httpClient = new DefaultHttpClient();
    HttpPost post = new HttpPost(url);

  • 设置Request header

    ```//以下参数因不同网站安全监测机制不同,所要求带的参数也不尽相同post.setHeader("Content-Type", "application/json;charset=UTF-8");post.setHeader("Host", "www.iconfont.cn");post.setHeader("Cookie", "UM_distinctid=15d5d87f8534ugkekhk9Vw");post.setHeader("Referer","http://www.iconfont.cn/search/index?q=java&page=2");post.setHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");```

  • 设置Data

    ```List<NameValuePair> params = new ArrayList<NameValuePair>();      //变化参数    params.add(new BasicNameValuePair("page", String.valueOf(page_number))); //传入页码    params.add(new BasicNameValuePair("q", "java")); //检索关键字    //固定参数    params.add(new BasicNameValuePair("cityEname", "henan"));     params.add(new BasicNameValuePair("sortType", "updated_at"));    params.add(new BasicNameValuePair("pageSize", "54")); //每页条数 54    params.add(new BasicNameValuePair("t", String.valueOf(new Date().getTime()))); //当前时间戳 1502713082550    params.add(new BasicNameValuePair("ctoken", "bL67K02mQl16IlJizxgeicon-font"));    post.setEntity(new UrlEncodedFormEntity(params,Consts.UTF_8)); ```

  • 获取Entity

    HttpResponse response = httpClient.execute(post);int statusCode = response.getStatusLine().getStatusCode();if(statusCode != 200){    System.out.print(statusCode);    return null;}HttpEntity entity = response.getEntity();String result = null;if (entity != null) {    result = EntityUtils.toString(entity, "utf-8");}EntityUtils.consume(entity);return result;

3.调度函数

  • 初始化参数和构造循环体

    String url = "http://www.iconfont.cn/api/icon/search.json";String keyword = "java"; //查询条件Integer page_number = 1; //起始页数while(true){    String json = Post(url, page_number);    Map<String, Object> data = JsonUtil.JsonToMap(json);    //解析数据}

  • 返回数据格式
    这里写图片描述

  • 解析返回数据

    • 查看是否出错

      if(data.isEmpty() || Integer.parseInt(data.get("code").toString()) != 200){                System.out.println("获取第" + page_number + "页数据出错!!");                break;            }
    • 获取键值对

      //上述结构的一个data键所对应的值            Map<String, Object> data_key = (Map<String, Object>) data.get("data");            //data中的icons键所对应的值            List<Map<String, Object>> icons = (List<Map<String, Object>>) data_key.get("icons"); 
    • 处理数据

      //{data={"count":103,"icons":[]}, code=200}if(icons.isEmpty()){        System.out.println("结束,共计:" + data_key.get("count"));         break;}else{    for(Map<String, Object> icon: icons){        //可以在此处进行数据解析        System.out.println(icon);         //可根据icon.get("")方式获取各个值    }    System.out.println("第" + page_number + "页,数据:" + icons.size() + "条数据");    page_number++; //继续下一页}
    • 输出

      第1页,数据:54条数据第2页,数据:49条数据结束,共计:103

翻页系列到此结束,接下来更新模拟登录。

原创粉丝点击