云锁其实是个服务器安全软件,主业也不是反爬虫,不过有一条是可以防止cc攻击,而爬虫行为就像是频次不高的cc攻击,因而直接请求目标站并不能返回目标内容。
最近正好做了个需求抓取 中国土地市场网 上的一些信息,这个网站刚好就使用了云锁。
也没有多高明,无非就是常用的:
这里不采用浏览器分析cookie 是因为浏览器一访问会有很多js 生成的本地cookie, 直接代码请求比较清爽直观
运行之后发现是js执行的跳转并不是服务器返回3xx跳转,所以无需指定是否跟随跳转
if __name__ == '__main__':
resp = requests.get("http://www.landchina.com/", timeout=5)
print("info:")
print(resp.text)
print("cookies:")
for key, value in resp.cookies.items():
print(f"key: {key} value: {value}")
仔细观察发现请求返回的html结果中有如下代码
function stringToHex(str) {
var val = "";
for (var i = 0; i < str.length; i++) {
if (val == "") val = str.charCodeAt(i).toString(16); else val += str.charCodeAt(i).toString(16);
}
return val;
}
function YunSuoAutoJump() {
var width = screen.width;
var height = screen.height;
var screendate = width + "," + height;
var curlocation = window.location.href;
if (-1 == curlocation.indexOf("security_verify_")) {
document.cookie = "srcurl=" + stringToHex(window.location.href) + ";path=/;";
}
self.location = "/?security_verify_data=" + stringToHex(screendate);
}
setTimeout("YunSuoAutoJump()", 50);
原来是执行了 YunSuoAutoJump() 这个方法生成了个跳转链接
就是使用dom方法获取浏览器长宽再进行哈希变换再执行跳转:
self.location = "/?security_verify_data=" + stringToHex(screendate);
上述请求返回携带的cookies:
key: yunsuo_session_verify value: 2972e332b013f2963dc1ca74531a44b6
2. 二话不说带上cookie, 拼接个跳转链接再请求一下,代码修改如下:
这里可以注意到哈希函数是固定的而浏览器的长宽也可以使固定的,所以我们可以不用研究哈希函数直接使用固定的stringToHex(screendate) 结果就行, 自己用浏览器访问一下就能得到结果
if __name__ == '__main__':
url = "http://www.landchina.com/"
resp = requests.get(url, timeout=5)
cookie = {}
for key, value in resp.cookies.items():
cookie[key] = value
resp = requests.get(
'{}{}'.format(url, '?security_verify_data=313932302c31303830'),
cookies=cookie
)
print(resp.text)
for key, value in resp.cookies.items():
cookie[key] = value
print(f'{key}: {value}')
html 内容和第一次请求一样依旧不是正确结果,不过又反回了一个cookie:
security_session_mid_verify: b621fcf2ed74e709c200e2af37eada46
3. 看来还要再携带返回的cookie进行一次请求,修改代码如下:
if __name__ == '__main__':
url = "http://www.landchina.com/"
resp = requests.get(url, timeout=5)
cookie = {}
for key, value in resp.cookies.items():
cookie[key] = value
resp = requests.get(
'{}{}'.format(url, '?security_verify_data=313932302c31303830'),
cookies=cookie
)
for key, value in resp.cookies.items():
cookie[key] = value
# 注意这里的cookie字典中存有第一次请求得到的 yunsuo_session_verify,和第二次请求得到的 security_session_mid_verify
resp = requests.get(
url,
cookies=cookie
)
print(resp.status_code)
print(resp.text)
这时我们发现返回的就是我们想要的结果了,至此完成整个云锁反爬的反反爬工作
封装如下
import requests
def get_cookies(url, proxies):
proxies = {'http': 'http://{}'.format(proxies), 'https': 'http://{}'.format(proxies)}
return {
'yunsuo_session_verify': requests.post(url, proxies=proxies).cookies.get('yunsuo_session_verify'),
'security_session_mid_verify': requests.post('{}{}'.format(url, '&security_verify_data=313932302c31303830'), proxies=proxies).cookies.get('security_session_mid_verify')
}
def get_proxy():
# 大规模爬取要增加代理,这里是伪代码啦
return prox
if __name__ == '__main__':
url = '你要抓取的url'
prox = get_proxy()
cookie = get_cookies()
resp = requests.get(
url,
proxies=proxies,
cookies=cookie
)
# 做你想做的吧
一些需要注意的事: