模拟 TLS 指纹实现反反爬

简介: 模拟 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

9a47873f1796c3ae569a27c21e531bcf.png

这是我基于浏览器访问的,它的字段都不是空,我们使用 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 模拟指纹则可以绕过这道防线。


本文参考自:

相关文章
|
云安全 安全
第二届WEBSHELL伏魔挑战赛开启报名
舞台已备好,等你来战!
1111 0
第二届WEBSHELL伏魔挑战赛开启报名
|
编解码 监控 网络协议
【那些反爬和反反爬】JA3指纹
【那些反爬和反反爬】JA3指纹
1566 0
|
8月前
|
人工智能 JSON API
Nacos 发布 MCP Registry,实现存量应用接口“0改动”升级到 MCP 协议
MCP(Model Calling Protocol)生态快速发展,Nacos作为MCP Registry,通过与Higress网关结合,实现“0代码”将存量API转化为MCP协议接口。本文详细解析了Nacos如何快速构建MCP Server,包括工具列表暴露、协议转换原理及优势。同时,通过高德API实例演示“0改动”适配流程。Nacos 3.0正式发布,定位AI应用服务管理平台,支持动态服务发现与配置管理,助力MCP生态发展。欢迎参与社区共建!
1396 1
|
7月前
|
人工智能 Java API
MCP客户端调用看这一篇就够了(Java版)
本文详细介绍了MCP(Model Context Protocol)客户端的开发方法,包括在没有MCP时的痛点、MCP的作用以及如何通过Spring-AI框架和原生SDK调用MCP服务。文章首先分析了MCP协议的必要性,接着分别讲解了Spring-AI框架和自研SDK的使用方式,涵盖配置LLM接口、工具注入、动态封装工具等步骤,并提供了代码示例。此外,还记录了开发过程中遇到的问题及解决办法,如版本冲突、服务连接超时等。最后,文章探讨了框架与原生SDK的选择,认为框架适合快速构建应用,而原生SDK更适合平台级开发,强调了两者结合使用的价值。
9717 33
MCP客户端调用看这一篇就够了(Java版)
|
Linux 网络安全 Python
linux centos上安装python3.11.x详细完整教程
这篇文章提供了在CentOS系统上安装Python 3.11.x版本的详细步骤,包括下载、解压、安装依赖、编译配置、解决常见错误以及版本验证。
10201 3
linux centos上安装python3.11.x详细完整教程
|
缓存 搜索推荐 数据挖掘
TPS和QPS是什么?都是什么区别?
TPS和QPS是什么?都是什么区别?
9716 4
|
12月前
|
人工智能 IDE 程序员
GitHub Copilot 免费了!程序员们的福音来了!
《GitHub Copilot 免费了!程序员们的福音来了!》 近日,GitHub 宣布其 AI 编程助手 GitHub Copilot 现在可以免费使用。曾经每月需支付 10 美元订阅费的 Copilot,现在向所有人开放免费版本,这对个人开发者、初学者和小型团队来说是个大好消息。免费版支持 GPT 和 Claude 模型,并提供每月 2000 次代码补全和 50 条聊天消息等核心功能。用户只需注册或登录 GitHub 账户,在 VS Code 中安装扩展并激活免费版即可使用。此外,Visual Studio Code 也完全免费,进一步降低了开发门槛。 除了
12060 7
GitHub Copilot 免费了!程序员们的福音来了!
|
JSON 网络协议 网络安全
详解新一代 HTTP 请求库:httpx
详解新一代 HTTP 请求库:httpx
1540 2
|
安全 Linux 网络安全
【工具使用】几款优秀的SSH连接客户端软件工具推荐FinalShell、Xshell、MobaXterm、OpenSSH、PUTTY、Terminus、mRemoteNG、Terminals等
【工具使用】几款优秀的SSH连接客户端软件工具推荐FinalShell、Xshell、MobaXterm、OpenSSH、PUTTY、Terminus、mRemoteNG、Terminals等
127103 0
|
数据采集 人工智能 数据可视化
Python selenium爬虫被检测到,该怎么破?
Python selenium爬虫被检测到,该怎么破?
1734 9