概述:本文将针对 Ja3 指纹检测风控进行处理,举例了一个案例并使用两种不同的破解方案进行突破,同时深入了解指纹间不同字符所代表的含义
指纹检测背景:
1、每一个设备、软件都有独属于自己的设备信息、版本号、加密算法、椭圆算法等等,而ja3指纹就是将这些信息进行了一个非常复杂的计算后得到的产物,在不做特殊处理的情况下,部分网站会短时间内大量相同指纹的请求视为爬虫进行封禁。
2、在使用requests这个模块的时候,由于requests这个模块底层调用的是ssl进行请求导致ja3指纹无法做出有效的调整,这个是这个模块的缺陷,包括目前市面上对requests进行指纹的修改大部分都是无效的(反编译或修改源文件的除外)
3、突破方案:目前突破的方案有多种
1、使用大佬改魔改的 curl_cffi 模块进行请求,但这种由于封装的太过于完善了,好处是用法简单,坏处是不能 “随心所欲”;
2、使用 pyhttpx 或 request-go 等模块进行自定义 ja3 指纹进行请求;
3、使用 js、go语言发起请求能够有效解决(因为主要讲的是python我这里先pass了)
特征:
1、响应数据里面出现 Just a moment... 等字样
2、在确保参数无问题的情况下对 curl 重放是成功的,但放在 python 或 js 代码中执行失败
好了废话不多说,直接开始
目标网站:aHR0cHM6Ly9waXhhYmF5LmNvbQ==
======= 正文开始 =======
一、首先对网站进行请求,确认风控类型
复制 curl 转 requests,放在python里请求发现非常明显的特征 Just a moment...,基本上看见这个大概率就确认是指纹检测了
响应结果:
二、风控突破(curl_cffi 模块)
目前市面上是有个国外的大神模拟好主流的浏览器指纹并封装好的模块 —— curl_cffi
官方链接:https://github.com/lexiforest/curl_cffi
优点:用法简单,可以无脑 requests,同时跟requests用法基本一致
缺点:面对较为严格的网站还是会出现无法请求的情况,同时无法自定义指纹
以上述网站为例:
from curl_cffi import requests
url = "https://pixabay.com/zh/videos/search/"
params = {
"pagi": "13"
}
response = requests.get(url,headers=headers,params=params,impersonate="chrome101")
print(response.text)
print(response)
运行结果:
这个时候响应的结果就正常了,同时他支持以下浏览器的版本:
备注:当出现chrome浏览器过不了的时候可以尝试一下使用苹果的浏览器 safari 说不定有奇效
- chrome99
- chrome100
- chrome101
- chrome104
- chrome107
- chrome110
- chrome116
- chrome119
- chrome120
- chrome123
- chrome124
- chrome99_android
- edge99
- edge101
- safari15_3
- safari15_5
- safari17_0
- safari17_2_ios
- safari18_0
- safari18_0_ios
三、风控突破(自定义 ja3 ,pyhttpx模块)
当遇到一个比较强的 ja3 检测的时候,这个时候 curl_cffi 可能效果就会不尽人意,这个时候就需要自己定义一个ja3的指纹来进行访问,这里比较推荐的是使用 pyhttpx 模块,这个模块还有一个很强的地方,就是会固定住请求头的顺序(有部分网站会检测请求头字典的顺序)
1、获取自己的指纹
在实现自定义Ja3之前要先了解指纹,首先获取自己的指纹,这个网站是有非常多的,可以挑一个自己喜欢的
https://tools.scrapfly.io/api/fp/ja3
https://tls.browserleaks.com/json
https://tls.peet.ws/api/clean
2、指纹参数说明
""" 假设ja3指纹是:原始ja3:771,4865-4866-4867-41195-49199-49296-49100-52393-52392-41171-49172-156-157-47-53,65281-18-27-43-0-5-51-13-11-17513-35-41-28-16-10-21,29-23-24,0-1-2 771: tls版本号(0x0303是771的十六进制) 4865-4866-4867-41195-49199-49296-49100-52393-52392-41171-49172-156-157-47-53:加密套件,用于协商在通信中使用的加密算法和参数 65281-18-27-43-0-5-51-13-11-17513-35-41-28-16-10-21:扩展信息,用于提供额外的功能或参数 29-23-24:椭圆曲线算法的标识符列表,用于在密钥交换中选择椭圆曲线算法 0-1-2:压缩算法的标识符列表,用于协商在通信中使用的压缩算法 """
3、设置自定义的指纹
使用上面的网站获取自己的指纹,然后携带指纹进行请求
代码:
import pyhttpx
ja3 = "771,4865-xxxx-xxx 自己的ja3指纹"
sess = pyhttpx.HttpSession(http2=True, ja3=ja3)
url = "https://pixabay.com/zh/videos/search/"
params = {
"pagi": "13"
}
response = sess.get(url,headers=headers,params=params)
print(response.text)
print(response)
有一个特别重要的重点!!
扩展信息:65281-18-27-43-0-5-51-13-11-17513-35-41-28-16-10-21中,
41属于会话恢复扩展,打开新的浏览器第一次访问是没有的,只有重新建立tcp连接,才会携带上次的信息,所以在采集的时候一定要把 41 给去掉!!
这也是我在采集目标网站的时候这里踩了很大的坑
携带 41 进行请求,报错 TCP 握手失败
去掉41后请求恢复正常:
总结:
目前使用 curl_cffi 的方法是比较简单的也很适合小白,但是如果需要进阶一点的话比较推荐pyhttpx,自由度也会更高一点,如果有不懂的或者有爬虫单子的话欢迎私聊。