天天看点

xhr请求有两个sessionid_两个爬虫例子

爬一个AJAX加载的网页

目前多数网站都不会将数据直接放在HTML里,而是采用异步加载的方式,原始页面不包含数据,只是一些样式,在页面加载完后,向服务器发送AJAX请求,从其他接口获取数据,处理后在页面上展示。

一些官方的网站数据,有不少是采用这种方式,比较典型的就是外汇交易中心里的一些数据,下面拿每日活跃债券统计这个功能做个例子。

如何看是不是AJAX请求

xhr请求有两个sessionid_两个爬虫例子

这种网站大家一般都见过,在左上角选择需要查询的日期,然后会显示出所需的数据,但是浏览器上地址栏中网址并没有变化。那在选择日期的时候到底发生了什么?可以通过开发者工具来进行分析。

Chorme

自带开发者工具,

Chorme

内核的Edge也包含此工具,感觉两个应该是一样的。在打开上面的页面后,按

F12

,打开开发者工具,就会看到图2的界面。

xhr请求有两个sessionid_两个爬虫例子

如果是

Chorme

可能是全英文的,Edge会有中文的显示。开发者工具里,最上面选择

网络

(官方的

Chorme

Network

),然后在下面筛选器的位置选择

XHR

,因为

AJAX

的请求类型就是

XHR

。目前开发者工具中是空的,因为在打开此工具后有任何操作,没有产生请求。

现在回到CFETS的网页上,换一个日期,就会发现开发者工具中多了一项

AtbDlyBltn

,类型为

xhr

,这就是点击查询后产生的

AJAX

请求。

xhr请求有两个sessionid_两个爬虫例子

单击这个请求后,查看详细信息,可以看到右边的

请求URL

http://www.chinamoney.com.cn/dqs/rest/dqs-u-bond/AtbDlyBltn

,请求方式为

POST

。在请求标头部分,

X-Requested-With: XMLHttpRequest

标记了这个请求就是

AJAX

。最下面的表单数据里有POST的具体数据:

lang: cn

searchDate: 2020-09-29

。再看右边的预览,这里是从请求获取的数据,其中

records

部分就是网页中显示的活跃债券的信息。(官方的

CHORME

是英文的,但顺序都是一样的,英文看一下也都看得明白。)

xhr请求有两个sessionid_两个爬虫例子
xhr请求有两个sessionid_两个爬虫例子

请求结果的提取

对这部分数据的请求是向

http://www.chinamoney.com.cn/dqs/rest/dqs-u-bond/AtbDlyBltn

POST日期和语言,

python

里的

requests

就可以完成模拟请求。代码如下。

前面就是一些基本的变量,

r = requests.post(BASE_URL, data=post_data)

发送请求的部分,取回的结果即在

r.text

中,是标准的

json

格式,我们所需要的成交数据就在

records

的部分,所以使用

python

中的

json

包,将其转为字典,字典中

records

的值为一个包含当日前十成交量债券数据的列表,列表中的每一个元素都是一个字典,对应网页中表格的一行。

如果要批量爬取数据,可以用

pandas

先生成一个包含所有日期的列表,然后逐日重复上面的爬取过程,而数据的存储比较简便的方式就是利用

pandas

存储到

Excel

里。具体代码如下。

加入

time.sleep(3)

的目的是为了防止访问过快被封IP,具体怎么个屏蔽规则我也不敢试,反正在用另一种方法爬这个页面的时候把公司的IP弄屏蔽了,同事也都看不了这个页面了,好在一天之后就恢复了。另一种方式最后会介绍。

另一个例子:爬中金所国债期货持仓数据

xhr请求有两个sessionid_两个爬虫例子

打开中金所的国债期货成交排名,一看这个页面就和CFETS的很像,打开网页源代码,搜索一下永安,果然也是没有,按照上面的操作看一下请求,果然也是

AJAX

的情况。

xhr请求有两个sessionid_两个爬虫例子

但是和CFETS不同的是,中金所的网站是请求方式是

GET

,而CFETS的是

POST

,还有就是在具体请求的URL里最后还包含了一个

id=

,后面会有一个数字,换了不同日期后,这个数字会改变,再换回原来的日期,还是会产生一个不同的数字,因此是一个与日期没有对应关系的随机数。但是不要紧,经过测试,随便写个数字应该就行。。。

xhr请求有两个sessionid_两个爬虫例子

具体的代码如下。

首先,和之前不一样的是

BASE_URL

,里面多了两个

{}

。我们再看两个请求的URL,下面两个图一个是请求2020年8月18日的T合约,一个是请求2020年9月10日的T合约,可以看到两个括号位置分别对应年份+月份和日期。将

BASE_URL

写成这种形式方便之后在批量请求时利用

format

来补充相关日期信息。

xhr请求有两个sessionid_两个爬虫例子
xhr请求有两个sessionid_两个爬虫例子

接下来就是

header

字典,这部分是请求头,与开发者工具中下图部分对应。

xhr请求有两个sessionid_两个爬虫例子

再下面就是请求,这里的用

requests.get

替代了之前的

requests.post

,因为中金所的网站的请求方式是

GET

BASE_URL.format(date[:6], date[6:])

就是把日期分成两个部分,分别填到

{}

的位置,形成一个与日期对应的URL,而第二个参数

headers=header

,是将请求头信息加入到请求中,其实在这个例子里并没有实际的作用,加不加都能获取数据,其他的网站可能会验证请求头,如果确实一些必要的信息,例如

User-Agent

Referer

Cookies

等,则会限制访问。在之后就是数据处理的过程,与请求数据无关,因为中金所返回的数据不是

json

而是

xml

,需要利用

xml

模块进行解析,然后转换成字典,写入

DataFrame

后保存。具体批量爬取的代码就不放了,思路和上面是一样的。这是爬取T合约的方法,要是爬取TF和TS,需要调整URL。

另一个被限制了的方法

这个方法是最开始不会上面方法时候用到的,简单粗暴,中金所似乎没有限制,但是外汇交易中心应该是限制了的,就是利用页面自带的导出功能。

中金所持仓数据下面有个

Excel

附件,链接地址是

http://www.cffex.com.cn/sj/ccpm/202009/30/T_1.csv

,链接也是一样的规律,日期分成了两个部分,用

requests.get

是可以下载下来的,然后将这些下载下来的

csv

文件用

pandas

等再处理一下,也可以得到数据。在

get

中是否需要

headers

,具体需要包含什么,我也没有具体试。而CFETS导出到excel后链接地址是

http://www.chinamoney.com.cn/dqs/rest/dqs-u-bond/AtbDlyBltnExcel?lang=cn&searchDate=2020-09-30

,地址的规律也都可以看出来,也可以下载下来,但是下了几个后,我就被屏蔽了,不知道是不是因为太快了,之前没有加入

sleep