网站四处罚信息反爬破解
在Chrome中请求列表页时,刷新网页观察网络请求发现,先是跳转到一个中转链接:http://www.pbc.gov.cn/WZWSREL3poZW5nd3Vnb25na2FpLzEyNzkyNC8xMjgwNDEvMjE2MTQyMS9pbmRleC5odG1s?wzwschallenge=V1pXU19DT05GSVJNX1BSRUZJWF9MQUJFTDUxODU2NjI=
,然后再跳转回到列表页。
下面我们来具体看看中间的过程:
请求列表页
http://www.pbc.gov.cn/zhengwugongkai/127924/128041/2161421/index.html
请求头中没有携带Cookie,请求响应返回的Cookie为:
wzws_cid=6fe01577596a409d77f565c225c8c5a664a89799db7d0985a62413f32f6ba6e2d15be123681d18238c4216ea84a3b705e2a6611466562bf4c66a22358bff5b241873a84dab388b5da80fc2ecf6a2acf41f764692145f8bb5a57762e2fe08c49c; path=/; expires=Thu, 19 Sep 2019 08:41:13 GMT
此时请求返回的是一个携带大量加密
js
的HTML文件;自动去请求
http://www.pbc.gov.cn/WZWSREL3poZW5nd3Vnb25na2FpLzEyNzkyNC8xMjgwNDEvMjE2MTQyMS9pbmRleC5odG1s?wzwschallenge=V1pXU19DT05GSVJNX1BSRUZJWF9MQUJFTDUxODU2NjI=
请求头中携带的Cookie为:
wzws_cid=6fe01577596a409d77f565c225c8c5a664a89799db7d0985a62413f32f6ba6e2d15be123681d18238c4216ea84a3b705e2a6611466562bf4c66a22358bff5b241873a84dab388b5da80fc2ecf6a2acf41f764692145f8bb5a57762e2fe08c49c
请求响应返回的Cookie为:
wzws_cid=6fe01577596a409d77f565c225c8c5a664a89799db7d0985a62413f32f6ba6e2d15be123681d18238c4216ea84a3b705b81cba9208ba6c30f9c7a9ed07941d8e; path=/; expires=Thu, 19 Sep 2019 08:41:13 GMT
此时请求返回的是一个302的重定向页面;
自动再次请求列表页
http://www.pbc.gov.cn/zhengwugongkai/127924/128041/2161421/index.html
请求头中携带的Cookie为:
wzws_cid=6fe01577596a409d77f565c225c8c5a664a89799db7d0985a62413f32f6ba6e2d15be123681d18238c4216ea84a3b705b81cba9208ba6c30f9c7a9ed07941d8e
请求响应中没有返回Cookie;
但是返回了我们想要获取的列表页内容;
通过观察总结,我们发现步骤2是为了返回给我们请求需要的真正的Cookie,只有携带步骤2返回的Cookie才可以成功请求到数据,所以我们每次只要进行一次步骤2的操作去获取cookie就可以了;但是,步骤2的请求链接是如何获取的呢?
我做了三次请求,分别将步骤2的url
(省略了前缀)都复制了下来:
/WZWSREL3poZW5nd3Vnb25na2FpLzEyNzkyNC8xMjgwNDEvMjE2MTQyMS9pbmRleC5odG1s?wzwschallenge=V1pXU19DT05GSVJNX1BSRUZJWF9MQUJFTDg2MzAxMQ==
/WZWSREL3poZW5nd3Vnb25na2FpLzEyNzkyNC8xMjgwNDEvMjE2MTQyMS9pbmRleC5odG1s?wzwschallenge=V1pXU19DT05GSVJNX1BSRUZJWF9MQUJFTDIwMjU3MjM=
/WZWSREL3poZW5nd3Vnb25na2FpLzEyNzkyNC8xMjgwNDEvMjE2MTQyMS9pbmRleC5odG1s?wzwschallenge=V1pXU19DT05GSVJNX1BSRUZJWF9MQUJFTDYxNjI1MzU=
仔细观察,发现变化的是wzwschalleng
参数的值,更准确地说,wzwschalleng
参数的前半部分V1pXU19DT05GSVJNX1BSRUZJWF9MQUJFTD
都是不变的,改变的只有末尾的八九个字符。
这里发现wzwschalleng
参数的值很像base64
编码,我们全部拿来解码:
1 | import base64 |
通过解码对比发现,改变的只有末尾的七位数字;到这里我们就该去思考如何获取每次变化的wzwschalleng
或者更精确的后面的这七位数字。
这时我们想到了,第一次请求之后返回的js
代码,几乎可以推测就是这段js
代码,生成了wzwschalleng
的值。
我们在chrome的source栏下面给网页打上script事件断点,这样当网页执行到该js
代码时会停下来,便于我们观察,具体操作如图:
注:当我们刷新无法在该js
代码处停下时,是因为缓存的原因,清空缓存后,使用Ctrl+F5
强制刷新
之后我们看到了全部的js
代码如下:
1 | eval(function(p, a, c, k, e, r) { |
经过漫长的三秒钟的冷静,开始研究这段一丢丢也看不懂的js
代码。
首先要找函数入口,从上到下看过来发现,先是执行了eval(function(p, a, c, k, e, r)...
,再就是从函数_0x33f22a()
开始执行。
我们在_0x33f22a()
函数内部打断点,查看变量值的情况,如下图所示:
我们发现变量_0xb14971
的值为WZWS_CONFIRM_PREFIX_LABEL4914759
,这个值看起来好像很熟悉,没错正是我们前面base64
解码后的值,将该值进行base64
编码就是wzwschalleng
的值。
那么我们看_0xb14971
的值是怎么算出来的,发现他后面调用了_0x344cd4
方法,我们进入该方法,打上断点查看变量值的的情况:
我们发现_0x3c9135
变量的值是一个七位的数字,后面return _0x53d9fc[_0x56ae('0x20', 'd2rH')](_0x56ae('0x21', 'Rau%'), _0x3c9135)
,我们用鼠标把这一串选中,发现其值为WZWS_CONFIRM_PREFIX_LABEL8455744
,因为我们上面得到的结论是,只要更改最后面这七位数字的值就可以得到每次变化的wzwschalleng
的值。所以我们只需要把这个最核心的函数抠出来就可以:
1 | function _0x344cd4() { |
我们的目标是能够独立运行该函数,所以需要去修改这段代码,在for循环之前都是定义变量,无需修改,for循环的终止条件中_0x56ae('0x1d', 'uGC9')
其实是"GjCbS"
,_0x56ae('0x1e', 'V2r4')
是length
。
小技巧:我们将这两个字符串,复制到chrome的console中,按回车看输出就知道了;在console中执行copy(_0x56ae('0x1e', 'V2r4'))
还可以直接复制出其值。
这里还有两个重要的变量,wzwsquestion
和wzwsfactor
,去哪找呢?这时候想起来,一开始不是执行了一段eval()
代码嘛,我们执行一下看看:
太巧了!这段代码,执行完之后,正好初始化了wzwsquestion
和wzwsfactor
这两个变量。
其实,我们仔细观察eval
执行时的默认参数值,可以发现这两个值隐藏其中,该函数做的工作只是将原始字符串做了分割之类的工作。
'var|dynamicurl|/WZWSREL2Z6aHNoYW5naGFpLzExMzU3Ny8xMTQ4MzIvMTE0OTE4L2luZGV4Lmh0bWw=|wzwsquestion|GT#rs1mW}J{x,GghI6|wzwsfactor|1574|wzwsmethod|WZWS_METHOD|wzwsparams|WZWS_PARAMS'
这就是那段原始的字符串,所以我们只要写正则匹配一下提出这两个值就可以了,所以最终我们只要改写_0x344cd4
方法就行了。
此外,还有一点要注意,原来的js
代码中为有这样一个语句_0x3c9135 += 0x1b207;
,其实我们保持原样也是可以的运行的,但是有必要指出,0x1b207
表示十六进制的111111
,不要和这段代码的变量形式_0x...
弄混。
下面是完整的爬取代码,包括改写后的_0x344cd4
方法:
1 | # _*_ coding:utf-8 _*_ |
上面的request_page方法中,也可以设置不允许重定向,那么其返回的状态码应该为302,我们只需要取其返回的cookie,然后拿去再去请求列表页即可。