相信大家在做爬虫的时候,都有过被反爬的经历,一旦网站识别是爬虫,就会拒绝请求。反爬机制有很多,最常见的便是通过请求头里的 User-Agent,举个例子。
import requests
import httpx
response = requests.get("http://www.baidu.com")
print(response.request.headers["User-Agent"])
"""
python-requests/2.28.0
"""
response = httpx.get("http://www.baidu.com")
print(response.request.headers["User-Agent"])
"""
python-httpx/0.23.3
"""
如果 User-Agent 不符合浏览器的格式,那么一定不是浏览器发出的,于是网站便可认定这属于爬虫。当然通过 User-Agent 识别属于最低级的方式,因为爬虫可以伪造自己的 User-Agent。
import requests
import httpx
response = requests.get("http://www.baidu.com",
headers={"User-Agent": "Chrome User-Agent"})
print(response.request.headers["User-Agent"])
"""
Chrome User-Agent
"""
response = httpx.get("http://www.baidu.com",
headers={"User-Agent": "IE User-Agent"})
print(response.request.headers["User-Agent"])
"""
IE User-Agent
"""
除了 User-Agent 之外,还可以通过请求头中的 Refer 字段判断是否为爬虫。比如你在 A 页面点击某个标签跳转到 B 页面,那么 Refer 就是 A 页面的地址。如果你直接访问的 B 页面,那么 Refer 就是空。
如果 B 页面必须通过点击 A 页面的标签才能跳转,那么网站便可以通过 Refer 来判断是否为爬虫。
当然啦,反爬机制还有很多,不同网站使用的策略不一样。但现在大部分的网站都使用了 HTTPS,在建立 HTTPS 连接的时候要先进行 TLS 握手,在握手的过程中会协商加密算法、交换密钥和验证双方的身份。
而将 TLS 握手产生的信息收集起来,并使用 JA3 算法生成一个哈希值,便得到了 TLS 指纹,基于该指纹可以标识、分类和跟踪使用特定 TLS 配置的客户端。
因此通过 JA3 哈希生成指纹便可以确定哪些是恶意流量,从而将其拒绝掉。换句话说,通过 TLS 指纹可以识别哪些是浏览器发出的正常请求,哪些是爬虫。
那么 TLS 指纹如何查看呢?可以通过以下几个网站。
https://tls.browserleaks.com/json
https://tls.peet.ws/
https://kawayiyi.com/tls
这是我基于浏览器访问的,它的字段都不是空,我们使用 Python 访问一下。
import requests
import httpx
user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/118.0.0.0 Safari/537.36"
response = requests.get("https://tls.browserleaks.com/json",
headers={"User-Agent": user_agent})
print(response.json())
"""
{'ja3_hash': '8d9f7747675e24454cd9b7ed35c58707',
'ja3_text': '771,4866-4867-4865-49196-49200-49195...',
'ja3n_hash': 'a790a1e311289ac1543f411f6ffceddf',
'ja3n_text': '771,4866-4867-4865-49196-49200-49195...',
'akamai_hash': '',
'akamai_text': ''}
"""
response = httpx.get("https://tls.browserleaks.com/json",
headers={"User-Agent": user_agent})
print(response.json())
"""
{'ja3_hash': '76f01df912881a05228c70b7f61bcbaa',
'ja3_text': '771,4866-4867-4865-49196-49200-49195...',
'ja3n_hash': '80a9bea1db8ce3a18047816ba1ee07e5',
'ja3n_text': '771,4866-4867-4865-49196-49200-49195...',
'akamai_hash': '',
'akamai_text': ''}
"""
如果使用爬虫,那么多次请求时的 ja3_hash 是不变的,并且 akamai_hash 和 akamai_text 均是空,基于该特征很容易识别是不是爬虫。即使我们更换代理,设置请求头,也无法改变这一点。
于是为了完美模拟浏览器,国外大佬开发出了 curl-impersonate,将 curl 底层依赖的库全部换成了浏览器使用的库,并且版本也是一致的,这样生成的指纹就和浏览器完全一样了。
而 curl_cffi 正是 curl-impersonate 的 Python binding,我们直接使用 pip 安装即可。
# 和 requests 接口是一致的
from curl_cffi import requests
# 但是多了一个 impersonate 参数,用于指定模拟哪个浏览器
response = requests.get("https://tls.browserleaks.com/json",
impersonate="chrome101")
print(response.json())
"""
{'ja3_hash': 'cd08e31494f9531f560d64c695473da9',
'ja3_text': '771,4865-4866-4867-49195-49199-49196...',
'ja3n_hash': 'aa56c057ad164ec4fdcb7a5a283be9fc',
'ja3n_text': '771,4865-4866-4867-49195-49199-49196...',
'akamai_hash': '8a32ff5cb625ed4ae2d092e76beb6d99',
'akamai_text': '1:65536;3:1000;4:6291456;6:262144|15663105||m,a,s,p'}
"""
# 当然也可以先创建 session
session = requests.Session()
# 然后基于 session 发请求
总共支持如下版本的浏览器:
我们选择 chrome110 即可,然后 curl_cffi 还支持异步发请求,可以和 asyncio 轻松集成。
import asyncio
from curl_cffi import requests
async def send_req():
async with requests.AsyncSession() as session:
response = await session.get(
"https://tls.browserleaks.com/json",
impersonate="chrome101"
)
print(response.json())
asyncio.run(send_req())
"""
{'ja3_hash': 'cd08e31494f9531f560d64c695473da9',
'ja3_text': '771,4865-4866-4867-49195-49199-49196...',
'ja3n_hash': 'aa56c057ad164ec4fdcb7a5a283be9fc',
'ja3n_text': '771,4865-4866-4867-49195-49199-49196...',
'akamai_hash': '8a32ff5cb625ed4ae2d092e76beb6d99',
'akamai_text': '1:65536;3:1000;4:6291456;6:262144|15663105||m,a,s,p'}
"""
由于指纹特征很难更改,因此通过指纹可以防御一大批爬虫,而通过 curl_cffi 模拟指纹则可以绕过这道防线。
本文参考自:
-
https://yifei.me/note/2719
-
https://github.com/yifeikong/curl_cffi
原文始发于微信公众号(古明地觉的编程教室):模拟 TLS 指纹实现反反爬
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/251307.html