python从入门到放弃自学笔记3-爬取北京市信访信件数据实战(抓包实现)

这次学会了一点抓包的内容,总结一下如何爬取ajax链接中的内容,如果抓包的时候看到有http请求其他的url(text/html) ,很可能就是ajax请求,一般用来获取动态数据,在页面中显示。发出ajax请求的时候 http请求头部一般有这个字段:X-Requested-With:XMLHttpRequest ,不过不一定都有!所谓python模拟ajax请求,实际上就是用python发起http请求,发送这个http请求所需要的数据可以通过抓包获取,构造一个一样的数据发送过去。Ajax的的全称是异步javascript and  XML,说的是用javascript调用浏览器后台线程来进行http请求,这样做的好处是不会阻塞浏览器主线程,主要表现就是用户可以继续操作页面,比如鼠标复制页面中的文字等。总之不要纠结Ajax, 它其实就是在浏览器后台线程进行http请求而已。然后看一下爬取的过程:

爬取链接为http://www.beijing.gov.cn/hudong/hdjl/com.web.search.mailList.flow,打开谷歌浏览器自带的开发者工具进行抓包,当点击下一页的时候,出现了下面的数据:

可以看到浏览器发送请求到了http://www.beijing.gov.cn/hudong/hdjl/com.web.search.mailList.mailList.biz.ext,而且请求头部中含有X-Requested-With:XMLHttpRequest字段,再看一下response中的数据:

{"PageCond":{"begin":6,"length":6,"count":33607,"totalPage":5602,"currentPage":2,"isCount":true,"isFirst":false,"isLast":false,"size":6},"mailList":[{"letter_type":"咨询","original_id":"AH20022500044","catalog_id":"住房公积金提取","letter_title":"进城务工人员与单位解除劳动关系,还可以申请销户提取住房公积金吗?","create_date":"2020-02-25","org_id":"北京住房公积金管理中心","keywords":null,"letter_status":"L07","ask_same_num":0,"reply_num":0,"support_num":0,"supervise_num":0,"isReply":true},{"letter_type":"咨询","original_id":"AH20022500027","catalog_id":"住房公积金提取","letter_title":"咨询公积金提取问题","create_date":"2020-02-25","org_id":"北京住房公积金管理中心","keywords":null,"letter_status":"L07","ask_same_num":null,"reply_num":null,"support_num":null,"supervise_num":null,"isReply":true},{"letter_type":"咨询","original_id":"AH20022400384","catalog_id":"住房公积金贷款","letter_title":"住房公积金是否可以跨区买房使用?","create_date":"2020-02-24","org_id":"北京住房公积金管理中心","keywords":null,"letter_status":"L07","ask_same_num":null,"reply_num":null,"support_num":null,"supervise_num":null,"isReply":true},{"letter_type":"咨询","original_id":"AH20022400286","catalog_id":"住房公积金提取","letter_title":"之前购买沈阳的住房提取过一次住房公积金,现在还需要提取怎样办理?","create_date":"2020-02-24","org_id":"北京住房公积金管理中心","keywords":null,"letter_status":"L07","ask_same_num":0,"reply_num":0,"support_num":0,"supervise_num":0,"isReply":true},{"letter_type":"咨询","original_id":"AH20022400284","catalog_id":"公积金缴纳","letter_title":"缓缴住房公积金","create_date":"2020-02-24","org_id":"北京住房公积金管理中心","keywords":null,"letter_status":"L07","ask_same_num":null,"reply_num":null,"support_num":null,"supervise_num":null,"isReply":true},{"letter_type":"咨询","original_id":"AH20022400256","catalog_id":"住房公积金贷款","letter_title":"公积金存款为零会不会导致销户或影响后续公积金贷款?","create_date":"2020-02-24","org_id":"北京住房公积金管理中心","keywords":null,"letter_status":"L07","ask_same_num":0,"reply_num":0,"support_num":0,"supervise_num":0,"isReply":true}]}

可知其中包括了我们需要的数据字段,不仅如此,里面PageCond中还包括了返回的数据个数,数据的起始位置等信息;

再查看一下请求的preview也就是请求的body:

 里面包括了请求所需要的返回的数据个数,所需数据的起始位置等信息,这样我们就可以在设置请求body时规定请求中的这类信息;

 附上爬取代码(用到了scrapy框架,需要了解的兄台可以看自学笔记1和2):

# -*- coding: utf-8 -*-
import json

import scrapy
class DemoSpider(scrapy.Spider):
    name = 'demo'
    allowed_domains = ['www.beijing.gov.cn']
    custom_settings = {                       #是对settings文件进行覆盖
        "DEFAULT_REQUEST_HEADERS": {         #DEFAULT_REQUEST_HEADERS用于覆盖settings中headers的内容
            # 请求报文可通过一个“Accept”报文头属性告诉服务端 客户端接受什么类型的响应。
            'accept': 'application/json, text/javascript, */*; q=0.01',
            # 指定客户端可接受的内容编码
            'accept-encoding': 'gzip, deflate',
            # 指定客户端可接受的语言类型
            'accept-language': 'zh-CN,zh;q=0.9',
            'Connection': 'keep-alive',  # 就是告诉服务器我参数内容的类型,该项会影响传递是from data还是payload传递
            'Content-Type': 'text/json',
            # 跨域的时候get,post都会显示origin,同域的时候get不显示origin,post显示origin,说明请求从哪发起,仅仅包括协议和域名
            'origin': 'http://www.beijing.gov.cn',
            # 表示这个请求是从哪个URL过来的,原始资源的URI
            'referer': 'http://www.beijing.gov.cn/hudong/hdjl/com.web.search.mailList.flow',
            # 设置请求头信息User-Agent来模拟浏览器
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36',
            'x-requested-with': 'XMLHttpRequest',
            # cookie也是报文属性,传输过去
            'Cookie': 'HDJLJSID = A39ABB5803EDEF95C60A2415C0FE8CC4;X - LB = 1.1.44.637df82f;__jsluid_h = f153ee53ef073d77a0f05187049b3e69;route = a2cec3cb28b0d59d32db7b39f74f56a5;_va_id = 6be1fba9ea2dfbca.1582601129.4.1582616679.1582608434.;_va_ses = *'
                    }
    }

    # 需要重写start_requests方法

    def start_requests(self):
        # 网页里ajax链接
        url = "http://www.beijing.gov.cn/hudong/hdjl/com.web.search.mailList.mailList.biz.ext"

        requests = []

        for i in range(0, 33750, 1000):
            my_data = {'PageCond/begin': i, 'PageCond/length': 1000}#这里在设置请求体,两个属性分别为请求获取数据开始的位置和每次获得数据的条数(每次获取数据量最好不要太大)
            # 模拟ajax发送post请求
            request = scrapy.http.Request(url, method='POST',
                                          callback=self.parse_model,
                                          body=json.dumps(my_data),#json.dumps()是对数据进行编码,形成json格式的数据,这是对请求body的要求
                                          encoding='utf-8')
            requests.append(request)
        return requests

    def parse_model(self, response):
        # 可以利用json库解析返回来得数据
        jsonBody = json.loads(response.text)
        size = jsonBody['PageCond']['size']
        data = jsonBody['mailList']

        listdata = {}
        fb = open('result.txt', 'a', encoding='utf-8')

        for i in range(size):
            listdata['letter_type'] = data[i]['letter_type']  # 信访类型
            listdata['letter_title'] = data[i]['letter_title']  # 信访标题
            listdata['create_date'] = data[i]['create_date']  # 信访时间
            listdata['org_id'] = data[i]['org_id']  # 回复单位
            fb.write(listdata['letter_type'] + ",")
            fb.write(listdata['letter_title'] + ",")
            fb.write(listdata['create_date'] + ",")
            fb.write(listdata['org_id'])
            fb.write('
')

爬取结果:

python小白的第一次抓包。。。

原文地址:https://www.cnblogs.com/123456www/p/12369109.html