问题
如题,爬取一带一路政府官网的时候,遇到了521报错。一查发现是js加密的问题。
该网站反爬原理,用我并不专业的语言描述如下:要求访问两次这个网站,第一次的时候会得到(Cookie和)一个js函数,这个函数执行之后会得到Cookie,第二次访问就利用这个Cookie来进行请求。
但大家也看到了,我的标题中是一个愤愤不平的“不管”。那么以下是我的心路历程。
解决
绕了很多弯路在解决js加密的问题上,企图解密js,获得js函数,然后通过python的execjs库来执行函数。然后遇到了很多问题,主要原因是这里的函数并不简单,有些地方execjs是不能解决的。
但后来缝缝补补之下也找到了方法,这里直接贴代码,有需要的朋友可以参考:
def crawler(CurrentRootURL):
print("开始>>>" + CurrentRootURL)
ua = UserAgent().random
headers = {
'Host': 'www.yidaiyilu.gov.cn',
'Referer': 'https://www.yidaiyilu.gov.cn/info/iList.jsp?cat_id=10149',
'User-Agent': ua,
}
rs = requests.session() #可以全局使用Cookie
resp = rs.get(CurrentRootURL,headers=headers)
txt_521 = ''.join(re.findall('<script>(.*?)</script>', resp.text))
cookie_id = '; '.join(['='.join(item) for item in resp.cookies.items()])
#编译生成cookie的js函数
func_return = txt_521.replace('eval', 'return')
content = execjs.compile(func_return)
eval_func = content.call('f')
#var = str(eval_func.split('=')[0]).split(' ')[1]
var = re.findall('var (.*?)=',eval_func)[0]
rex = r">(.*?)</a>"
rex_var = re.findall(rex, eval_func)[0]
mode_func = eval_func.replace('document.cookie=','return ').replace(';if((function(){try{return !!window.addEventListener;}', ''). \
replace("catch(e){return false;}})()){document.addEventListener('DOMContentLoaded'," + var + ",false)}",''). \
replace("else{document.attachEvent('onreadystatechange'," + var + ")}",''). \
replace(r"setTimeout('location.href=location.pathname+location.search.replace(/[\?|&]captcha-challenge/,\'\')',1500);",''). \
replace('return return', 'return eval'). \
replace("document.createElement('div')",
'"https://www.yidaiyilu.gov.cn/"'). \
replace(r"{0}.innerHTML='<a href=\'/\'>{1}</a>';{0}={0}.firstChild.href;".format(var, rex_var), '')
#执行js函数,获得Cookie
content = execjs.compile(mode_func)
#print(mode_func)
cookies_js = content.call(var)
__jsl_clearance = cookies_js.split(';')[0]
cookies = "{0};{1};".format(cookie_id, __jsl_clearance)
headers["Cookie"] = cookies
res = requests.get(CurrentRootURL, headers=headers)
HTMLText = res.text
return HTMLText
如此,便可以访问网站了。
主要参考了博文:
爬虫遭遇状态码521陷阱 破解js加密cookie
然后还有一篇,也是爬取一带一路官网的博文,但是刚刚没有找到网址,大家可以再搜一搜,
但是!!!
这并不是我今天的重点!
我的重点是,后来直接在某篇博文的评论区发现了一个方法:
`options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-automation']) # 此步骤很重要,设置为开发者模式,防止被各大网站识别出来使用了Selenium
self.browser = webdriver.Chrome(executable_path=chromedriver_path, options=options)
self.wait = WebDriverWait(self.browser, 10) #超时时长为10s
self.browser.get(self.url) # 这次返回的是 521 相关的防爬js代码
self.browser.get(self.url) # 调用2次 self.browser.get 解决 521 问题
html = self.browser.page_source
print(html)`
What???用selenium竟然如此简单????
但仔细一想,没毛病啊,网页要求我访问两次,那我就模拟浏览器访问两次呗。
没什么,就是写出来分享一下,纪念我逝去的头发。
总结
1.还是一个道理:多看评论区。
2.怎么反爬,就怎么爬。