python模拟TLS指纹实现反爬取

 更新时间:2023年10月18日 15:01:38   作者:古明地觉的编程教室  
这篇文章主要为大家详细介绍了如何利用python模拟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/

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

到此这篇关于python模拟TLS指纹实现反爬取的文章就介绍到这了,更多相关python模拟TLS指纹内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 如何利用opencv对拍摄图片进行文字识别

    如何利用opencv对拍摄图片进行文字识别

    在有些工程中有时候我们需要对图片文字识别,下面这篇文章主要给大家介绍了关于如何利用opencv对拍摄图片进行文字识别的相关资料,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2024-03-03
  • Pycharm2022最新版无法换源解决方法

    Pycharm2022最新版无法换源解决方法

    本文主要介绍了Pycharm2022最新版无法换源解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • 关于sklearn包导入错误:ImportError: cannot import name Type解决方案

    关于sklearn包导入错误:ImportError: cannot import name Type解

    这篇文章主要介绍了关于sklearn包导入错误:ImportError: cannot import name‘Type‘解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • python 叠加等边三角形的绘制的实现

    python 叠加等边三角形的绘制的实现

    这篇文章主要介绍了python 叠加等边三角形的绘制的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • python smtplib发送带附件邮件小程序

    python smtplib发送带附件邮件小程序

    这篇文章主要为大家详细介绍了python smtplib发送带附件邮件小程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • 使用Python Flask实现简易文件上传功能

    使用Python Flask实现简易文件上传功能

    在平时工作中,文件上传是一项常见的需求,例如将应用异常时通过脚本生成的dump文件收集起来进行分析,但实现起来却可能相当复杂,在本文中,我们将探讨如何使用Flask实现文件上传功能,编写Dockerfile将应用程序通过docker部署,需要的朋友可以参考下
    2024-05-05
  • python多进程下实现日志记录按时间分割

    python多进程下实现日志记录按时间分割

    这篇文章主要为大家详细介绍了python多进程下实现日志记录按时间分割,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • Python基于Opencv识别两张相似图片

    Python基于Opencv识别两张相似图片

    这篇文章主要介绍了Python基于Opencv识别两张相似图片的步骤,帮助大家更好的理解和学习使用python,感兴趣的朋友可以了解下
    2021-04-04
  • 代码分析Python地图坐标转换

    代码分析Python地图坐标转换

    这篇文章主要介绍了Python地图坐标转换的相关知识点以及分享了相关的代码实例,对此有兴趣的朋友学习下。
    2018-02-02
  • Python pygame实现图像基本变换的示例详解

    Python pygame实现图像基本变换的示例详解

    pygame的transform中封装了一些基础的图像处理函数,这篇文章主要为大家介绍了pygame实现图像的基本变换,例如缩放、旋转、镜像等,感兴趣的小伙伴可以了解一下
    2023-11-11

最新评论