從保哥的臉書貼文看到 OpenAI 網站有特別的保護, 經過推論與驗證後, 發現是使用了 TLS Fingerprint 保護。簡單的來說, HTTPS 協定在真正傳輸資料前會有一段驗證程序, 伺服器端會送出電子憑證讓瀏覽器確認它的確是欲連接網站的伺服器, 而 TLS Fingerprint 則是讓伺服器在驗證程序中從客戶端送過來的設定資料以 JA3 等演算法計算出電子指紋來區別瀏覽器的種類。curl 由於採用了 openssl 程式庫進行驗證程序, 傳送的設定資料和其它瀏覽器明顯都不一樣, 伺服端很容易識別出來。若用 curl 連接 OpenAI 的文章會得到:
$ curl -I https://openai.com/index/introducing-structured-outputs-in-the-api/
HTTP/2 403
....
Python 的 requests 套件也一樣使用了 openssl 程式庫, 所以也會得到同樣的錯誤:
>>> import requests
>>> requests.get('https://openai.com/index/introducing-struc
... tured-outputs-in-the-api/')
<Response [403]>
如果要取得正確的網頁內容, 就要仿照瀏覽器的方式傳送一模一樣的設定資料進行驗證程序, 相關細節可以參考這篇文章。目前已經有善心人士幫我們解決這個問題, 你可以使用修改過不使用 openssl 程式庫的 curl 版本--curl-impersonate:
$ ./curl_safari15_5 -I https://openai.com/index/introducing-structured-outputs-in-the-api/
HTTP/2 200
除了有 curl 指令本身以外, 他也幫你準備好了扮演不同版本的各式瀏覽器的腳本, 像是上例就是假扮 Safari 15.5, 對於伺服器來說, 這個腳本的行為就像是真正的瀏覽器一樣。
如果要使用 Python 取得正確的網頁, 則可以使用 curl_cffi 套件, 他的作用就跟 curl-impersonate 一樣:
>>> from curl_cffi import requests
>>> requests.get('https://openai.com/index/introducing-struc
... tured-outputs-in-the-api/')
<Response [403]>
>>> r = requests.get('https://openai.com/index/introducing-s
... tructured-outputs-in-the-api/', impersonate="edge101")
>>> r.status_code
200
加上 impersonate 引數就可以指定要扮演的瀏覽器, 正確取回網頁內容了。
Top comments (0)