curl_cffi ウェブスクレイピング: PythonにおけるブラウザTLSフィンガープリント
Specialist in Anti-Bot Strategies
TL;DR:
- curl_cffiは、実際のブラウザのTLSハンドシェイクを模倣するPythonのHTTPクライアントであり、接続を指紋認証するサーバーはスクリプトクライアントではなくChromeとして認識します。
requests.get(url, impersonate="chrome")の呼び出しは、ブラウザのJA3フィンガープリントを提示し、HTTP/2を交渉します。ブラウザプロセスは不要です。- JA3ハッシュは毎回異なり、それは正しいです。GREASEはハンドシェイクにランダムな値を挿入し、実際のChromeも同様に行います。
- curl_cffiはJavaScriptを実行しないため、クライアントレンダリングされたページでは空のシェルを返します。このガイドは、curl_cffiからの0の引用ブロックと、レンダリング付きのScrapelessからの10の引用ブロックでそれを証明します。
- TLSフィンガープリンティングが壁となっている場合はcurl_cffiを、ページがレンダリングを必要とする場合や、チャレンジがクリアされている場合、またはIPローテーションが必要な場合はScrapelessを利用してください。
- TLS模倣だけでは到達できないページのためにScrapelessの無料プランから始めてください。
プレーンなPython HTTPクライアントは、HTMLのバイトを送信する前にターゲットが読み取れる情報を持っています。それはそのTLSハンドシェイクです。ClientHelloに含まれる暗号方式と拡張機能のセットはブラウザのものとは異なり、そのハンドシェイクを指紋認証するサーバーは、フィンガープリンティングだけでリクエストをブロックすることができます。curl_cffiは、本物のブラウザのTLS署名を借用することによってそのギャップを埋めます。
このガイドでは、curl_cffiがブラウザのフィンガープリントを示し、JA3ハッシュが一定でない理由を説明し、curl_cffiが越えられない境界を示します。ページが実際のブラウザを必要とする場合、Scrapeless Universal Scraping APIが引き継ぎます。以下のすべての数字は、実際の実行から得られたものです。
curl_cffiの機能
curl_cffiは、curl-impersonateに基づいたrequestsスタイルのHTTPクライアントであり、その役割はTLSハンドシェイクを特定のブラウザのように見せることです。ハンドシェイクを検査するサーバーは、ClientHelloのバージョン、暗号方式、拡張を要約したJA3フィンガープリントを計算します。デフォルトのPythonクライアントは、ブラウザが生成しないフィンガープリントを生成しますが、curl_cffiは特定のブラウザのものを生成します。curl_cffiリポジトリに、そのプロファイルを模倣できるブラウザのバージョンがリストされています。
curl_cffiが行わないことは、ブラウザを実行することです。JavaScriptエンジンはなく、レンダリングもなく、挑戦の解決もありません。それはフィンガープリントであり、ブラウザではありません。
インストール
curl_cffiは、単一のpipインストールです。
bash
pip install curl_cffi
ブラウザフィンガープリントを模倣する
ブラウザ名を指定してimpersonateを渡すと、curl_cffiはそのブラウザのTLSハンドシェイクを構築します。以下のリクエストは、フィンガープリンティングサービスに何を見たかを報告します。
python
from curl_cffi import requests
response = requests.get("https://tls.peet.ws/api/all", impersonate="chrome", timeout=30)
fingerprint = response.json()
print("http version:", fingerprint["http_version"])
print("ja3 hash:", fingerprint["tls"]["ja3_hash"])
サービスはHTTP/2を報告します。これはブラウザが交渉し、デフォルトクライアントは通常行わないものであり、JA3ハッシュも同様です。
text
http version: h2
ja3 hash: 9a23d5cedcea13483954537602158034
上記のja3 hash値は1回の実行の結果です。スクリプトを再度実行すると、値は変わります。それはバグではありません。GREASEメカニズムはClientHelloにランダムな予約値を挿入し、実際のChromeも同様のことを行うため、JA3ハッシュは接続によって異なります。ブラウザらしさを保持するのは、ハンドシェイクの形状であり、これはフィンガープリントチェックが実際に評価するものです。
curl_cffiが停止する場所
ブラウザのTLSフィンガープリントは、リクエストをハンドシェイクチェックを通過させますが、ページをレンダリングしません。JavaScriptでそのコンテンツを構築するサイトでは、curl_cffiはサーバーが送信したものを正確に返しますが、それは空のシェルであり、どれだけのTLS模倣でもそれを満たすことはできません。ここではレンダリングツールが必要です。
シェルにScrapelessのキーを設定してください。実行時に本物のキーを使用し、プレースホルダーをソースから外してください。
bash
export SCRAPELESS_API_KEY="sk_your_key_here"
以下のスクリプトは、完璧なChromeフィンガープリントを持つcurl_cffiと、レンダリングを有効にしたScrapelessの2つの方法でJavaScriptでレンダリングされた引用ページを取得します。
python
import json
import os
import urllib.request
from curl_cffi import requests
JS_PAGE = "https://quotes.toscrape.com/js/"
response = requests.get(JS_PAGE, impersonate="chrome", timeout=30)
print("curl_cffi status:", response.status_code)
print("curl_cffi quote blocks:", response.text.count('class="quote"'))
def scrapeless(url: str) -> str:
payload = json.dumps(
{"actor": "unlocker.webunlocker", "input": {"url": url, "js_render": True, "headless": True}}
).encode()
request = urllib.request.Request(
"https://api.scrapeless.com/api/v2/unlocker/request",
data=payload,
headers={"x-api-token": os.environ["SCRAPELESS_API_KEY"], "Content-Type": "application/json"},
method="POST",
)
with urllib.request.urlopen(request, timeout=90) as response:
return json.loads(response.read())["data"]
html = scrapeless(JS_PAGE)
print("scrapelessの引用ブロック数:", html.count('class="quote"'))
curl_cffiは200をクリーンに取得し、引用はゼロです。なぜなら、引用はJavaScriptによって描画されるため、実行されません。Scrapelessはページをレンダリングし、引用が表示されます。
text
curl_cffi ステータス: 200
curl_cffi 引用ブロック数: 0
scrapeless 引用ブロック数: 10
この200は罠です:リクエストは成功するため、何も問題がないように見えますが、コンテンツが存在しません。二つのツールは異なる問題に応えます。curl_cffiはTLSフィンガープリントチェックを突破しますが、レンダリングを行ったり、チャレンジをクリアしたり、IPを回転させたりはしません。フィンガープリントの概念については、TLSフィンガープリンティングを回避する方法のガイドが、サーバーが測定するものとその理由を説明しています。
このプロセスをサイト全体に対して実行する前に、そのrobots.txtと利用規約を読みましょう。ロボット排除プロトコルは、サイトが自動化クライアントに避けるように求めるパスを示し、それを守ることでスクレイパーの持続可能性が保たれます。
フィンガープリントだけではアクセスできないページの準備はできていますか?無料のScrapelessアカウントを作成して、それらをレンダリングしましょう。
結論
curl_cffiは一つの仕事に対して最適なツールです:PythonリクエストのTLSハンドシェイクをブラウザのように見せかけることにより、ブラウザプロセスなしでフィンガープリントチェックをクリアします。これは正確であり、その限界も同様に正確です。なぜなら、JavaScriptを実行せず、クライアントレンダリングされたページの空のシェルを返すからです。ハンドシェイクが壁であるときはこれを使用し、レンダリング、チャレンジのクリア、または新しいIPが必要な場合はScrapelessにページを渡してください。上記のスクリプトから始めて、目の前の壁に応じてツールをマッチさせましょう。
Scrapelessの無料プランから始めるでレンダリングページを取得し、定期的な仕事にサイズを合わせる際はScrapelessの料金を確認しましょう。
FAQ
Q: curl_cffiは実際に何を偽装していますか?
curl_cffiはブラウザのTLSハンドシェイクとそのHTTP/2設定を偽装しますので、サーバーが見るClientHelloはデフォルトのPythonクライアントではなく、名前付きブラウザバージョンと一致します。ブラウザのJavaScriptエンジンやレンダリングは偽装していません。ネットワークレベルのフィンガープリントだけを扱っています。
Q: リクエストを実行するたびにJA3ハッシュが変更されるのはなぜですか?
GREASEによるもので、ランダムな予約値がTLS ClientHelloに挿入されます。本物のChromeもこれを行うため、JA3ハッシュは接続間で変動しますが、ハンドシェイクの意味的な形はブラウザらしさを保ちます。変わるハッシュは期待されるものであり、偽装に失敗した兆候ではありません。
Q: curl_cffiはJavaScriptでレンダリングされたページをスクレイピングできますか?
いいえ。curl_cffiにはJavaScriptエンジンがないため、クライアントレンダリングページでは初期のHTMLシェルを200ステータスで返し、レンダリングされたコンテンツは返しません。そのようなページにはScrapelessのようなレンダリングツールを使用し、curl_cffiはすでにレスポンスにコンテンツがあるエンドポイントのために使い続けてください。
Q: curl_cffiはrequestsとどう違いますか?
requestsライブラリは標準的なPython TLSハンドシェイクを送信し、フィンガープリンティングサーバーがフラグを立てることができるのに対し、curl_cffiはブラウザのハンドシェイクをimpersonate引数を通じて送信します。APIはそれ以外は馴染み深いもので、requests.get(url, impersonate="chrome")はフィンガープリンティングでブロックされていたコードに対するドロップインに近いです。
Q: ブラウザのTLSフィンガープリントはブロック回避に十分ですか?
TLSフィンガープリントチェックには十分ですが、それ以上ではありません。チャレンジページ、行動分析、IPの評判は別の防御策で、curl_cffiはそれに触れません。そのため、それらが関わる場合はレンダリング、チャレンジ処理、またはフィンガープリントに加えてのプロキシ回転が必要です。
Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。



