模拟 TLS 指纹实现反反爬

相信大家在做爬虫的时候,都有过被反爬的经历,一旦网站识别是爬虫,就会拒绝请求。反爬机制有很多,最常见的便是通过请求头里的 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

模拟 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 发请求

总共支持如下版本的浏览器:

模拟 TLS 指纹实现反反爬

我们选择 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

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!