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

本次抓取地址: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.json
Request Method:POST
Status Code:200 OK
Remote Address:140.205.34.99:80
Referrer 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.01
Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,en-US;q=0.8,en;q=0.6,zh;q=0.4
Connection:keep-alive
Content-Length:98
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Cookie:UM_distinctoDITj
Host:www.iconfont.cn
Origin:http://www.iconfont.cn
Referer:http://www.iconfont.cn/search/index?q=java&page=1
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36
X-Requested-With:XMLHttpRequest

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

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

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


请求参数:

q:java
sortType:updated_at
page:1
pageSize:54
t:1502713725794
ctoken: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
      

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值