zoukankan      html  css  js  c++  java
  • 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小白的第一次抓包。。。

  • 相关阅读:
    JSON初试
    for ...in 、for each ...in、 for...of(https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/for...of)
    WPF MVVM 模式下的弹窗
    『简易日志』NuGet 日志包 SimpleLogger
    WPF 让一组 Button 实现 RadioButton 的当前样式效果
    IIS 错误解决:当前标识没有对 Temporary ASP.NET Files 的写访问权限
    [读书笔记] 《大话设计模式》
    WPF 原生绑定和命令功能使用指南
    ASP.NET Core MVC 网站学习笔记
    在香蕉派的树莓派系统上配置 Syncthing 自启动
  • 原文地址:https://www.cnblogs.com/123456www/p/12369109.html
Copyright © 2011-2022 走看看