一日一技: Python 如何突破反爬蟲指紋 JA3

攝影:產品經理 

好菜上桌

今天,我們來介紹如何在 Python 裏面,使用 requests 請求網站的時候,修改 JA3 指紋。

requests 是基於 urllib3 實現的。要修改 JA3 相關的底層參數,所以我們今天要修改 urllib3 裏面的東西。

我們知道 JA3 指紋裏面,很大的一塊就是 Cipher Suits,也就是加密算法。而 requests 裏面默認的加密算法如下:

ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:!aNULL:!eNULL:!MD5

冒號分割了不同的加密算法。這些加密算法每一種順序其實就對應了一個 JA3 指紋字符串,只要我們修改這個順序,就能得到不同的 JA3 字符串。

在 requests 裏面,要修改 Cipher Suits 中的加密算法,需要修改 urllib3 裏面的 ssl 上下文,並實現一個新的 HTTP 適配器 (HTTPAdapter)。在這個適配器裏面,我們在每次請求的時候,隨機更換加密算法。但需要注意的是!aNULL:!eNULL:!MD5就不用修改了,讓他們保持在最後。

涉及到的代碼如下:

from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.ssl_ import create_urllib3_context

ORIGIN_CIPHERS = ('ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:'
'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES')


class DESAdapter(HTTPAdapter):
    def __init__(self, *args, **kwargs):
        """
        A TransportAdapter that re-enables 3DES support in Requests.
        """
        CIPHERS = ORIGIN_CIPHERS.split(':')
        random.shuffle(CIPHERS)
        CIPHERS = ':'.join(CIPHERS)
        self.CIPHERS = CIPHERS + ':!aNULL:!eNULL:!MD5'
        super().__init__(*args, **kwargs)
        
        
    def init_poolmanager(self, *args, **kwargs):
        context = create_urllib3_context(ciphers=self.CIPHERS)
        kwargs['ssl_context'] = context
        return super(DESAdapter, self).init_poolmanager(*args, **kwargs)

    def proxy_manager_for(self, *args, **kwargs):
        context = create_urllib3_context(ciphers=self.CIPHERS)
        kwargs['ssl_context'] = context
        return super(DESAdapter, self).proxy_manager_for(*args, **kwargs)

在一般情況下,當我們實現一個子類的時候,__init__的第一行應該是super().__init__(*args, **kwargs),但是由於init_poolmanagerproxy_manager_for是複寫了父類的兩個方法,這兩個方法是在執行super().__init__(*args, **kwargs)的時候就執行的。所以,我們隨機設置 Cipher Suits 的時候,需要放在super().__init__(*args, **kwargs)的前面。

有了適配器以後,我們使用 requests 時,初始化一個 Session,然後把這個適配器綁定到特定的網站上:

import requests
headers = {'User-Agent''Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.67'}
s = requests.Session()
s.headers.update(headers)

for _ in range(5):
    s.mount('https://ja3er.com', DESAdapter())
    resp = s.get('https://ja3er.com/json').json()
    print(resp)

其中,s.mount的第一個參數表示這個適配器只在https://ja3er.com開頭的網址中生效。

運行效果如下圖所示:

可以看到,ja3_hash已經改變了,說明我們請求時的 JA3 指紋已經發生了改變。

JA3 裏面,還有參數ExtensionsEllipticCurvesEllipticCurvePointFormats,我還不知道怎麼修改。如果有知道的同學,可以留言告訴我。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/7VJHCl2ht4pjkgIdcOKc5w