爬虫遭遇状态码521陷阱 破解js加密cookie

发布于 2019-08-15  150 次阅读


版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_27302597/article/details/79411808

最近接了个小单,遇到一个很头疼的问题,返回的状态码无限521,在网上查阅了各种资料后,终于解决了问题返回200。

首先咱们先贴上网址:点击打开链接

首先我们按照传统的方法:

  1. import requests
  2. headers={
  3. 'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36'
  4. }
  5. req=requests.get('https://www.seebug.org/vuldb/ssvid-92666',headers=headers).status_code
  6. print(req)
  7. /usr/bin/python3.5 /home/pipidi/Spider/lianjia/lianjia/spiders/__init__.py
  8. 521
  9. Process finished with exit code 0

可以说是毫无疑问 返回的是521 

下面贴出两种解决办法:

(1):直接复制request header

我们可以打开谷歌F12 找到其中的network 可以找到本网站地址的一个html 文件 直接复制所有他的头部

  1. import requests
  2. from copyheaders import headers_raw_to_dict
  3. header=b'''Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
  4. Accept-Encoding:gzip, deflate, br
  5. Accept-Language:zh,en-US;q=0.9,en;q=0.8
  6. Cache-Control:max-age=0
  7. Connection:keep-alive
  8. Cookie:__jsluid=9536c75cdfa3e7e8c38d59bcbf4fc98b; csrftoken=YzAMB2QogF2YmzpruqWI5vdsfeH9PSx5; Hm_lvt_6b15558d6e6f640af728f65c4a5bf687=1519809319,1519880921; __jsl_clearance=1519885472.708|0|IQ9%2FbeQ6cfNLaEZUk2QzXhNEtL8%3D; Hm_lpvt_6b15558d6e6f640af728f65c4a5bf687=1519885477
  9. Host:www.seebug.org
  10. Upgrade-Insecure-Requests:1
  11. User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36'''
  12. req=requests.get('https://www.seebug.org/vuldb/ssvid-92666',headers=headers_raw_to_dict(header)).status_code
  13. print(req)
  14. 200
  15. Process finished with exit code 0

就可以返回200,但是在实际爬取的过程中,会发现他还是会时不时返回521,并且cookie 是饼干屑具有时效性,不可能一直保存,所以方法1也不能说是最优解,下面我们来介绍一下方法2


(2):使用exejs执行js代码返回cookie

首先,我们先用带User-Agent的request去访问这个网站,还是令人沮丧,返回的是521

  1. import requests
  2. header={'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36'}
  3. req=requests.get('https://www.seebug.org/vuldb/ssvid-92666',headers=header).status_code
  4. print(req)
  5. 521
  6. Process finished with exit code 0

然后我们输出他的内容 使用requests.get().text方法

哇!? 看看看这是啥? 懂一点前端的同学估计都顿悟出来了 这!就是JS代码

查阅了很多大佬的博客,我发现 这是一种js加密cookie的手法

先访问第一次访问 返回521 并且给浏览器设置cookies 在第二次刷新的时候,你的浏览器就可以用设置上的cookie自动访问了

但是咱的爬虫不一样,无法加载js,就一直卡在第一次访问了

对此 我们的做法是让Python运行js代码,获取cookies 并且加到下次访问的头部

行!就这么做!

我们首先获取返回的源代码

  1. def get_521_content():
  2. headers={
  3. 'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36'
  4. }
  5. req=requests.get('https://www.seebug.org/vuldb/ssvid-92666',headers=headers)
  6. cookies=req.cookies
  7. cookies='; '.join(['='.join(item) for item in cookies.items()])
  8. txt_521=req.text
  9. txt_521=''.join(re.findall('<script>(.*?)</script>',txt_521))
  10. return (txt_521,cookies)

我们需要返回的分别是两个 第一个是网页的源代码 第二个是后台设置的cookie

然后我们对拿来的js代码进行修改并且运行

我使用的Python 执行js的模块是execjs ,在这里我也不过多赘述

主要的修改是将eval 替换成return 让他有返回值给咱看到

  1. def fixed_fun(function):
  2. func_return=function.replace('eval','return')
  3. content=execjs.compile(func_return)
  4. evaled_func=content.call('f')
var l=function(){while(window._phantom||window.__phantomas){};var cd,dc='__jsl_clearance=1519886795.502|0|';cd=[((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![]))-~~~[]-~-~{}-~~~[]-~-~{}+[]+[]),[4],(-~~~[]+[]+[])+(-~~~[]+[]+[]),(-~~~[]+[]+[]),(-~~~[]+[]+[])+[(-~[]|-~-~{})+(2<<-~[])],(-~~~[]+[]+[])+[4],(2+[[], ~~!{}][~~{}]),((-~-~{})*[(-~-~{}<<-~[])]+[]+[]),((+[])+[[], ~~!{}][~~{}]),(-~~~[]+[]+[])+((+[])+[[], ~~!{}][~~{}]),((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![]))+[[], ~~!{}][~~{}]),(-~~~[]+[]+[])+(-~![]+((-~![]<<-~![])<<-~[])+[]+[[]][~~[]]),[[-~-~{}]*((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![])))],(-~~~[]+[]+[])+[[-~-~{}]*((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![])))],(-~~~[]+[]+[])+(2+[[], ~~!{}][~~{}]),(-~~~[]+[]+[])+((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![]))+[[], ~~!{}][~~{}]),[(-~[]|-~-~{})+(2<<-~[])],(-~![]+((-~![]<<-~![])<<-~[])+[]+[[]][~~[]])];for(var i=0;i<cd.length;i++){cd[i]=[([-~[]-~[]-~[]-~[]][-~[]]+[]+[]).charAt(-~[-~~~[]-~(-~((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![]))))]),'HE',(2+[[], ~~!{}][~~{}])+[-~[]/~~[]+[]+[]][0].charAt(7)+(((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![])))/~~[]+[]).charAt(-~-~{})+[!{}+[[]][~~!{}]][0].charAt((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![])))+(-~~~[]+[]+[]),(2+[[], ~~!{}][~~{}]),'SG','D',[{}+[[]][~~!{}]][0].charAt(8),((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![]))+[[], ~~!{}][~~{}]),'T',(((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![])))/~~[]+[]).charAt(-~-~{})+[-~[]/~~[]+[]+[]][0].charAt(7)+[!{}+[[]][~~!{}]][0].charAt((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![])))+[-~[]/~~[]+[]+[]][0].charAt(7),'%',(-~![]+((-~![]<<-~![])<<-~[])+[]+[[]][~~[]])+((+[])+[[], ~~!{}][~~{}]),[-~[]/~~[]+[]+[]][0].charAt(7),'k%','x','FE','SEA',[!-[]+[]+[]][0].charAt(-~-~{})][cd[i]]};cd=cd.join('');dc+=cd;setTimeout('location.href=location.href.replace(/[\?|&]captcha-challenge/,\'\')',1500);document.cookie=(dc+';Expires=Thu, 01-Mar-18 07:46:35 GMT;Path=/;');};if((function(){try{return !!window.addEventListener;}catch(e){return false;}})()){document.addEventListener('DOMContentLoaded',l,false);}else{document.attachEvent('onreadystatechange',l);}

我们可以看到代码解密出来有变成了新的一串js代码

我们可以吧他放到html文件里面运行

我这里是直接放到exejs中运行的,对代码也进行了各种修改,最重要的是将document.cookie=()函数替换成return这样就可以直接用print输出返回的内容了,对于其他的修改,大家只要那里报错删那里就行。

  1. mode_func=evaled_func.replace('while(window._phantom||window.__phantomas){};','').\
  2. replace('document.cookie=','return').replace(';if((function(){try{return !!window.addEventListener;}','').\
  3. replace("catch(e){return false;}})()){document.addEventListener('DOMContentLoaded',l,false);}",'').\
  4. replace("else{document.attachEvent('onreadystatechange',l);}",'').replace(r"setTimeout('location.href=location.href.replace(/[\?|&]captcha-challenge/,\'\')',1500);",'')
  5. content = execjs.compile(mode_func)
  6. cookies=content.call('l')
  7. __jsl_clearance=cookies.split(';')[0]
  8. return __jsl_clearance

经过了一堆修改之后,

  1. if __name__ == '__main__':
  2. func=get_521_content()
  3. content=func[0]
  4. cookie_id=func[1]
  5. print(cookie_id)
  6. cookie_js=fixed_fun(func[0])
  7. print(cookie_js)

__jsl_clearance=1519886795.502|0|fysySG50HEux2yfs1Te%2FEOSEAyk%3D

我们会惊奇的发现,Python执行了js代码,并且返回了一段cookie,他就是我们想要的!之后我们需要做的事就比较轻松了,只需要把后台设置的__jsluid 和js设置的cookie __jsl_clearance一起加入我们的浏览器头就可以正常访问了

  1. headers={
  2. 'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36',
  3. 'Cookie': cookie_id+';'+cookie_js} #一定要和第一次访问的user-agent一模一样
  4. code=requests.get('https://www.seebug.org/vuldb/ssvid-92666',
  5. headers=headers).text
  6. print(code)

需要注意的是 User-Agent 一定要和第一次访问设置的一模一样,不然照样返回521,这也困扰了我很久

  1. print(req.status_code)
  2. print(len(req.text))
  3. /usr/bin/python3.5 /home/pipidi/Spider/pass_521.py
  4. 200
  5. 64382
可以放肆的爬取了,如果遇到521,就调用第一个访问的函数,运行js换新的cookie就行!


源码  GitHub点击打开链接





把一切平凡的事做好即不平凡,把一切简单的事做好即不简单。