クラシックな状況:WildberriesやOzonの価格監視用スクリプトが自宅のノートパソコンで完璧に動作するが、VPSに移行すると403エラー、キャプチャ、またはIPによる即時禁止が発生する。開発者はヘッダーを変更し、遅延を追加するが、結果は変わらない。問題はほとんどの場合、パーサーのコード自体ではなく、リクエストを行う環境にある。サーバーでパーサーが安定して動作するために変更すべき7つの具体的な理由を解説します。
なぜローカルではすべてが動作し、サーバーでは禁止されるのか
自宅のコンピュータからパーサーを起動すると、サイトはプロバイダーの通常の住宅用IPアドレスからのリクエストを認識し、慣れ親しんだ地域から、実際のブラウザ環境で(SeleniumやPlaywrightを使用している場合)リクエストが行われます。しかし、同じスクリプトがドイツ、オランダ、またはアメリカのVPSに移行すると、状況は一変します:IPはデータセンターに属し、TLSフィンガープリンティングはライブラリの異なるバージョンのために異なる可能性があり、サーバーのタイムゾーンはIPのジオロケーションと一致せず、リクエストの頻度は急激に増加します。なぜなら、サーバーは24時間365日稼働しているからです。
Wildberries、Ozon、Avito、そしてほとんどの大手マーケットプレイスのアンチボットシステムは、もはやUser-Agentだけを見ているわけではありません。彼らはIPの種類、リクエストの速度と定期性、ページ上での行動、ヘッダーとTLSパラメータの一致、クッキーの有無、セッションの履歴など、数十の信号の組み合わせを分析しています。ローカルマシンはほとんどのポイントで偶然にチェックを通過しますが、サーバーはほぼすべてのポイントで失敗します。以下に、各理由の詳細な分析を示します。
理由1: データセンターのIPではなく、住宅用IP
これは80%のケースでの理由№1です。VPSやクラウドサーバー(AWS、DigitalOcean、Hetzner、通常のVDSホスティング)のIPアドレスはデータセンターのデータベースに存在します — これらのプロバイダーのASNは公に知られており、アンチボットシステムによってトラフィックの即時フィルタリングに使用されます。マーケットプレイスは、95%の自動化されたパーシングがサーバーのIPから行われるため、これらのリストを優先的に使用します。
解決策は、視覚的に通常のインターネットユーザーと異ならないIPを使用することです。Wildberries、Ozon、Avitoのパーシングには、住宅用プロキシが最適です:これは、通常の加入者に発行された実際のIPアドレスです。アンチボットシステムは、このリクエストをデータセンターのサーバーからのものではなく、生きたユーザーからのトラフィックとして認識し、ほとんどのブロックを即座に解除します。
理由2: IPのローテーションとリクエスト頻度の制限がない
ローカルマシンでは、テスト中に20〜50のリクエストを手動で行い、サイトはそれに気づきません。しかし、サーバーでは、スクリプトがcronで5分ごとに実行され、1つのIPから数千の商品カードを連続して処理します。このようなパターンは、アンチボットシステムへの直接的な信号です:実際の人間が1時間で3000ページのカタログを一度も休まずに開くことはできません。
プロキシプールでIPのローテーションを導入し、一定の時間内に1つのアドレスへのリクエスト数を制限する必要があります。実用的なルールは、商品カードに対して1分間に1つのIPから30〜60のリクエストを超えないことです。リクエストのバッチごとにアドレスを自動的に変更することが重要です。Pythonでプロキシプールを介してローテーションを設定する例:
import requests
proxies_pool = [
"http://user:[email protected]:9000",
"http://user:[email protected]:9001",
"http://user:[email protected]:9002",
]
def get_page(url, session_id):
proxy = proxies_pool[session_id % len(proxies_pool)]
resp = requests.get(
url,
proxies={"http": proxy, "https": proxy},
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"},
timeout=10
)
return resp.text
大量の商品カードを1日に収集する場合、リクエストごとにIPを自動的にローテーションするプロキシを使用する方が便利です。これにより、手動でアドレスのリストを保持する必要がなくなります。
理由3: ヘッダーとUser-Agentがブラウザに似ていない
多くのパーサーはrequestsやaiohttpを使用して、最小限のヘッダーセットまたはライブラリの標準User-Agentでリクエストを送信しますが、これはすぐにスクリプトを示します(例えば、python-requests/2.31.0)。ローカルマシンでは、ブラウザを介してヘッダーのセットが完全です:Accept、Accept-Language、Accept-Encoding、Sec-Ch-Ua、Refererなど — それらの組み合わせは自然に見えます。
実際のブラウザの完全なヘッダーセットをコピーし、送信順序を含める必要があります — 一部のアンチボットシステムはこれすらもチェックします。さらに、TLSフィンガープリンティングのバージョンと同期してUser-Agentをローテーションすることが重要です(次のポイントを参照)。そうしないと、ブラウザのヘッダーと実際のTLSクライアントの不一致が新たなボットの信号となります。
理由4: TLS/JA3フィンガープリンティングがスクリプトを示す
これはあまり知られていませんが、サーバーでの禁止の非常に一般的な理由です。requests、urllib、aiohttpライブラリは、ChromeやFirefoxの実装とは異なるTLSハンドシェイクの実装を使用します。アンチボットシステムはTLS接続のJA3/JA4フィンガープリンティングを計算し、Pythonスクリプトのフィンガープリンティングは、ヘッダーが完璧にコピーされていても、実際のブラウザのフィンガープリンティングとは全く異なります。
解決策は、ブラウザのTLSフィンガープリンティングをエミュレートするライブラリを使用することです(例えば、Pythonのcurl_cffi、tls-client、またはPlaywright/Puppeteerを使用した完全なヘッドレスブラウザ)。もう一つの選択肢は、クリーンなHTTPクライアントではなく、アンチデテクトツールと組み合わせた管理されたブラウザエンジンを介して作業することです。ここでは、TLSとヘッダーが実際のブラウザエンジンによって生成され、ライブラリのエミュレーションではありません。
理由5: タイムゾーン、ロケール、DNSサーバー
スクリプトがSeleniumやPlaywrightを介してブラウザをエミュレートしている場合、アンチボットシステムはシステムのタイムゾーン、インターフェースの言語、DNSリゾルバー、さらには実際のサーバーのIPのWebRTCリークをチェックすることがあります。フランクフルトのデータセンターにあるVPSがUTCのシステムタイムゾーンとホスティングプロバイダーのDNSを使用し、モスクワのIPを持つプロキシを使用している場合、ジオデータの明確な不一致が生じます — これは検出のための最も信頼性の高い信号の1つです。
環境のすべてのパラメータ — タイムゾーン、ブラウザの言語、DNS、WebRTCによるジオロケーション — は、リクエストに使用されるIPアドレスの地域に一致している必要があります。この問題を解決するために作成されたのがアンチデテクトブラウザです:Dolphin Anty、AdsPower、Multilogin、Octo Browser、GoLoginは、各プロキシ用に個別の「ブラウザプロファイル」を設定でき、タイムゾーン、ロケール、画面解像度、WebRTCがIPのジオロケーションに自動的に調整されます。
理由6: リクエストパターンが「ロボット化」しすぎている
人間はさまざまな間隔でカタログをスクロールし、ランダムな商品をクリックし、時には戻って、ページを不均一にスクロールします。サーバースクリプトは通常、均等な間隔(例えば、厳密に2秒ごと)でリクエストを行い、必要なURLにのみアクセスし、「ノイズ」を伴わずに — 画像やスクリプトを読み込まず、商品カードの前にホームページを訪問することなく行います。
何を変更するか:ランダムな遅延を追加する(固定の2秒ではなく、1.5秒から6秒までのランダム)、時折中間ページにアクセスする(カテゴリー→カード、APIへの直接リクエストではなく)、ヘッドレスブラウザを介してスクロールやマウスの動きをエミュレートする。これにより、データ収集の時間が増加しますが、禁止の数が大幅に減少します。
理由7: セッションとクッキーがリクエスト間で保存されない
サーバー上のパーサーは、各リクエストごとに新しいrequestsセッションを作成することが多く — クッキーなし、保存された認証トークンなし、訪問履歴なし。WildberriesやOzonのようなマーケットプレイスは、最初の訪問時に一時的なクッキーとトークンを発行し、それ以降のリクエストはそれなしでは疑わしく見えます。まるで各リクエストが新しい匿名の訪問者によって行われているかのようです。
正しいスキーム:1つのセッション(requests.Session()またはブラウザのコンテキスト)をプロキシプールの1つのIPに結びつけ、リクエストのシリーズ全体にわたってクッキーを保存します。プロキシを変更する際は、新しいユーザーを模倣するために新しいセッションを開始し、古いクッキーを新しいIPで使用し続けないようにします — これも不一致を生じさせ、ブロックを引き起こします。
チェックリスト: 何を順番に変更するか
サーバーでパーサーが安定して禁止され、ローカルでは動作する場合、この順序で変更を確認してください — そうすれば、原因をより早く見つけることができます:
| ステップ | 確認すること | 変更すること |
|---|---|---|
| 1 | サーバーのIPの種類 | 直接のホスティングIPの代わりに住宅用プロキシに切り替える |
| 2 | リクエストの頻度 | IPのローテーションとアドレスへのリクエスト数を制限する |
| 3 | リクエストヘッダー | 実際のブラウザの完全なヘッダーセットをコピーする |
| 4 | TLSフィンガープリンティング | クリーンなrequestsの代わりにcurl_cffi / ヘッドレスブラウザを使用する |
| 5 | タイムゾーンとロケール | IPの地域に合わせてDolphin Anty / AdsPowerでプロファイルを設定する |
| 6 | 行動パターン | 遅延をランダム化し、中間ページを追加する |
| 7 | セッションとクッキー | リクエストのサイクル全体で1つのIPに1つのセッションを結びつける |
WildberriesやOzonのカタログを高頻度でパーシングする場合、数千ページを迅速に巡回することが重要であり、通常は2種類のプロキシを組み合わせます:データセンターのプロキシは技術的なリクエスト(可用性チェック、ステータスコード)用で、住宅用プロキシは商品カードからのデータ収集のために使用され、実際のユーザーに偽装することが重要です。マーケットプレイスやAvitoのモバイルアプリの場合、時にはモバイルプロキシの方が効果的です。なぜなら、ASNによる自動ブロックリストにかかることが少ないからです。
結論
サーバーでのパーサーの禁止は、ローカルバージョンが動作する場合、ほとんど常にスクリプトのロジックではなく、環境に関連しています:IPの種類、TLSフィンガープリンティング、ヘッダー、タイムゾーン、リクエストパターン、セッション管理。最も一般的な理由(データセンターのIP)から最も目立たない理由(タイムゾーンとIPの地域の不一致)まで、7つの理由を順番に確認することで、データ収集の主要なビジネスロジックを変更することなく、パーサーの安定した動作を回復できます。
Wildberries、Ozon、またはAvitoの価格や在庫を大量に収集している場合、IPの変更から始めてください:標準のVPSアドレスの代わりに住宅用プロキシを試してみてください — ほとんどの場合、ヘッダーやTLSフィンガープリンティングの設定を始める前に、70%のブロックを解消できます。