マーケットプレイスのパーシング、ソーシャルメディアの自動化、またはデータ収集のためにプロキシを使用する際、最も一般的な問題は、リクエストがハングしたり、データが失われたりすることです。プロキシサーバーがタイムリーに応答しない場合や、接続が切断される場合、スクリプトが数分間ハングすることがあります。その結果、時間、データ、お金を失うことになります。
このガイドでは、プロキシを使用する際のタイムアウト(タイムアウト)とリトライロジック(再試行ロジック)を正しく設定する方法を示します。さまざまなタスクに対してどのタイムアウト値を使用するか、エラー時に自動的に再接続する方法、リクエストを失わない方法を学びます。この記事は、Pythonでコードを書く人にも、既製のパーシングツールを使用する人にも適しています。
プロキシを使用する際のタイムアウトが重要な理由
例えば、あなたがWildberriesで10,000商品を対象に価格パーサーを起動したとします。スクリプトはプロキシを介して動作しており、バンを避けるためです。すべてが順調に進んでいますが、523回目のリクエストでプロキシサーバーが応答を停止します。おそらく、過負荷または一時的に利用できないためです。タイムアウトが設定されていない場合、スクリプトは無限に応答を待ち続けます(または、システムタイムアウトが2〜5分経過するまで)。その結果、パーシングが停止し、時間を失い、問題に気付くまでに数時間が経過する可能性があります。
タイムアウトとは、サーバーからの応答を待つ最大時間です。この時間内にサーバーが応答しない場合、リクエストは中断され、別のプロキシを介して再試行するか、エラーをログに記録することができます。これはプロキシを使用する際に特に重要です。なぜなら:
- プロキシサーバーは不安定である可能性がある — 特に公開されているものや安価なもの。質の高い住宅プロキシでさえ、実際のユーザーがインターネットから切断されたために接続を失うことがあります。
- ターゲットサイトがIPをブロックする可能性がある — プロキシがバンされた場合、まったく応答しないか、非常に遅く応答します(キャプチャやリダイレクトを返す)。
- ネットワーク遅延は予測不可能である — 特に他国のプロキシを使用する場合。リクエストは複数の中間ノードを経由する可能性があります。
- 大量の操作は安定性を必要とする — 100,000ページをパーシングする場合や50のInstagramアカウントを運営する場合、たとえ1%のハングしたリクエストでも= 1,000の失われた操作です。
正しく設定されたタイムアウトがなければ、スクリプトは利用できないプロキシを待つために時間を浪費し、動作するプロキシに切り替えることができません。これは作業の速度と結果の安定性に直接影響します。
タイムアウトの種類: connect, read, total timeout
理解し、別々に設定する必要がある3つの主要なタイムアウトの種類があります。多くの初心者の開発者やパーサーのユーザーは、1つの一般的なタイムアウトだけを設定し、それが問題を引き起こすことがあります。
1. Connect timeout(接続タイムアウト)
これは、プロキシサーバーとの接続を確立するために割り当てられた時間です。この時間内に接続が確立されない場合、リクエストは中断されます。Connect timeoutは、クライアントとプロキシ間の初期ハンドシェイク(TCPハンドシェイク)を担当します。
発生する場合: プロキシサーバーが利用できない、過負荷、またはIPがファイアウォールによってブロックされている。
推奨値:
- 高速なデータセンタープロキシ: 3-5秒
- 住宅プロキシ: 5-10秒
- モバイルプロキシ: 10-15秒(モバイルインターネットは遅い)
2. Read timeout(読み取りタイムアウト)
これは、プロキシとの接続が確立された後、ターゲットサーバーからの応答を待つ時間です。この時間内にサーバーがデータを返し始めない場合、リクエストは中断されます。Read timeoutは、サーバーがリクエストを受け入れたが「ハング」して応答を返さない状況から保護します。
発生する場合: ターゲットサイトがリクエストを遅く処理している、過負荷、または疑わしいリクエストを意図的に遅らせている。
推奨値:
- シンプルなページ(HTML)のパーシング: 10-15秒
- JavaScriptレンダリングを伴うパーシング: 30-60秒
- APIリクエスト: 5-10秒
- 大きなファイルのダウンロード: 120秒以上
3. Total timeout(総タイムアウト)
これは、接続、リクエストの送信、応答の受信と読み取りを含む、リクエスト全体の実行にかかる最大時間です。Total timeoutは、「非常停止スイッチ」であり、どのリクエストも指定された時間を超えて実行されないことを保証します。
使用する場合: 各リクエストが厳密な時間枠内に収まることが重要な場合(例えば、アービトラージのためのリアルタイムパーシング)。
公式: Total timeout = Connect timeout + Read timeout + 20-30%の余裕
重要: すべてのライブラリやツールがconnectとreadタイムアウトの個別設定をサポートしているわけではありません。たとえば、Pythonのライブラリrequestsでは、両方の値をタプルとして指定できます: timeout=(5, 15)、ここで5はconnect、15はreadです。
さまざまなタスクに対する最適なタイムアウト値
正しいタイムアウト値は、タスク、プロキシの種類、ターゲットサイトによって異なります。タイムアウトが短すぎると、多くの偽のエラーが発生します(プロキシは動作していますが、あなたはそれを却下します)。長すぎると、死んだプロキシを待つために時間を失います。
| タスク | Connect timeout | Read timeout | コメント |
|---|---|---|---|
| Wildberries, Ozonのパーシング | 5-7秒 | 15-20秒 | マーケットプレイスは多くの商品を含むページを遅く返すことがあります |
| Avito, Yandex.Marketのパーシング | 5-7秒 | 10-15秒 | 通常は高速なサイトですが、疑わしいIPをブロックすることがあります |
| Instagram, TikTokの自動化 | 7-10秒 | 20-30秒 | モバイルプロキシを使用してください — 遅いですが安定しています |
| Facebook Ads APIとの連携 | 5秒 | 10-15秒 | APIは通常高速ですが、レート制限時に遅くなることがあります |
| Selenium/Puppeteerを介したパーシング | 10秒 | 60-120秒 | JavaScriptレンダリングには時間がかかり、特に遅いプロキシではそうです |
| プロキシの大量チェック | 3-5秒 | 5-7秒 | 迅速な可用性チェック、遅いプロキシは却下されます |
アドバイス: 保守的な(より長い)タイムアウトから始め、エラーログを分析しながら徐々に短くしてください。動作しているプロキシで多くのタイムアウトエラーが発生している場合は、値を増やしてください。スクリプトが遅くなる場合は、短くしてください。
リトライロジック: 再試行を正しく設定する方法
タイムアウトはハングしたリクエストの問題を解決しますが、データ損失の問題は解決しません。プロキシが応答しなかった場合、エラーが発生し、そのリクエストを失うことになります。だからこそ、リトライロジック(再試行ロジック)が非常に重要です。
リトライロジックとは、エラーが発生した際にリクエストを自動的に再試行することです。正しい設定の基本原則は以下の通りです:
1. 再試行が必要なエラーを特定する
すべてのエラーを再試行する必要はありません。例えば:
- 再試行が必要なエラー: タイムアウト、接続拒否、プロキシエラー、502/503/504(サーバーの一時的なエラー)、レート制限(429)
- 再試行が必要ないエラー: 404(ページが見つかりません)、403(アクセスが永遠に禁止されています)、401(認証が無効)、データ検証エラー
2. 試行回数を設定する
最適なリトライ回数は、データの重要性によって異なります:
- 重要でないタスク(分析のためのパーシング)の場合: 2-3回の試行
- 重要なタスク(競合の価格監視)の場合: 3-5回の試行
- クリティカルなタスク(広告アカウントの操作)の場合: 5-10回の試行
3. 指数バックオフを使用する
リクエストを即座に再試行しないでください — これは問題を悪化させる可能性があります(例えば、サーバーが過負荷の場合)。試行の間に増加する遅延を使用してください:
- 1回目の試行: すぐに
- 2回目の試行: 1-2秒後
- 3回目の試行: 4-5秒後
- 4回目の試行: 10-15秒後
公式: 遅延 = 基本遅延 * (2 ^ 試行回数)。例えば: 1秒、2秒、4秒、8秒、16秒。
4. 再試行時のプロキシのローテーション
最も重要なルール: 再試行時には、プールから別のプロキシを使用してください。1つのプロキシがリクエストを実行できなかった場合、再試行時に成功する可能性は低いです。しかし、別のプロキシは高い確率で成功します。
これは、数百または数千のIPアドレスを持つ住宅プロキシを使用する場合に特に重要です。各リトライ時には、プールから新しいランダムなIPを取得してください。
Pythonでのタイムアウトとリトライの設定例
人気のあるライブラリを使用して、Pythonでタイムアウトとリトライロジックを実装する実践的な例を見てみましょう。
例1: requestsでの基本設定
requestsライブラリは、PythonでのHTTPリクエストに最も人気があります。タイムアウトとシンプルなリトライを設定する方法は次のとおりです:
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# リトライロジックの設定
retry_strategy = Retry(
total=5, # 最大5回の試行
backoff_factor=1, # 遅延: 1, 2, 4, 8, 16秒
status_forcelist=[429, 500, 502, 503, 504], # リトライのためのエラーコード
allowed_methods=["HEAD", "GET", "POST", "PUT", "DELETE"]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session = requests.Session()
session.mount("http://", adapter)
session.mount("https://", adapter)
# プロキシの設定
proxies = {
'http': 'http://username:password@proxy.example.com:8080',
'https': 'http://username:password@proxy.example.com:8080'
}
# タイムアウト付きでリクエストを実行
try:
response = session.get(
'https://www.wildberries.ru/catalog/electronics',
proxies=proxies,
timeout=(5, 15) # connect timeout 5秒、read timeout 15秒
)
print(f"成功! ステータス: {response.status_code}")
print(f"レスポンスのサイズ: {len(response.content)} バイト")
except requests.exceptions.Timeout:
print("エラー: タイムアウトを超えました")
except requests.exceptions.ProxyError:
print("エラー: プロキシに問題があります")
except requests.exceptions.RequestException as e:
print(f"リクエストエラー: {e}")
この例では、セッションレベルで自動リトライを設定しました。エラー429、500、502、503、504が発生した場合、ライブラリは自動的にリクエストを最大5回、指数的な遅延で再試行します。
例2: リトライ時のプロキシのローテーション
各試行時にプロキシをローテーションするより高度な例:
import requests
import random
import time
# プロキシプール(実際のプロキシに置き換えてください)
PROXY_POOL = [
'http://user:pass@proxy1.example.com:8080',
'http://user:pass@proxy2.example.com:8080',
'http://user:pass@proxy3.example.com:8080',
'http://user:pass@proxy4.example.com:8080',
]
def make_request_with_retry(url, max_retries=5, base_delay=1):
"""
リトライとプロキシのローテーションを伴うリクエストを実行します
"""
for attempt in range(max_retries):
# プールからランダムなプロキシを選択
proxy = random.choice(PROXY_POOL)
proxies = {'http': proxy, 'https': proxy}
try:
response = requests.get(
url,
proxies=proxies,
timeout=(5, 15),
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}
)
# ステータスコードを確認
if response.status_code == 200:
return response
elif response.status_code in [429, 500, 502, 503, 504]:
# 一時的なエラー - 再試行
print(f"試行 {attempt + 1}: コード {response.status_code}, 再試行中...")
else:
# 永続的なエラー - 試行を中止
print(f"エラー {response.status_code}, 試行を中止します")
return None
except (requests.exceptions.Timeout,
requests.exceptions.ProxyError,
requests.exceptions.ConnectionError) as e:
print(f"試行 {attempt + 1}: エラー {type(e).__name__}, 再試行中...")
# 最後の試行でない場合は、指数的な遅延を待つ
if attempt < max_retries - 1:
delay = base_delay * (2 ** attempt)
print(f"次の試行まで {delay} 秒待機...")
time.sleep(delay)
print("すべての試行が尽きました")
return None
# 使用例
result = make_request_with_retry('https://www.ozon.ru/category/smartfony-15502/')
if result:
print(f"成功! {len(result.content)} バイトのデータを取得しました")
else:
print("リクエストを実行できませんでした")
このコードは、各試行時にプールから新しいランダムなプロキシを選択し、リクエストの成功率を大幅に向上させます。
例3: tenacityライブラリの使用
リトライロジックをより柔軟に管理するために、専門のライブラリtenacityを使用できます:
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
import requests
@retry(
stop=stop_after_attempt(5), # 最大5回の試行
wait=wait_exponential(multiplier=1, min=1, max=30), # 指数的な遅延 1-30秒
retry=retry_if_exception_type((requests.exceptions.Timeout,
requests.exceptions.ProxyError,
requests.exceptions.ConnectionError))
)
def fetch_with_proxy(url, proxy):
"""
デコレーターを介して自動リトライを行う関数
"""
proxies = {'http': proxy, 'https': proxy}
response = requests.get(url, proxies=proxies, timeout=(5, 15))
response.raise_for_status() # HTTPエラー時に例外を発生させる
return response
# 使用例
try:
result = fetch_with_proxy(
'https://www.avito.ru/rossiya/telefony',
'http://user:pass@proxy.example.com:8080'
)
print(f"成功! ステータス: {result.status_code}")
except Exception as e:
print(f"すべての試行の後、リクエストを実行できませんでした: {e}")
tenacityライブラリは、デコレーターを介してリトライの非常に柔軟な設定を提供します。インストール: pip install tenacity
コードなしでのパーシングのための既製のソリューション
プログラマーでない場合や、開発に時間を節約したい場合は、タイムアウトとリトライロジックを内蔵した既製のパーシングツールがあります。コードを書く必要はなく、グラフィカルインターフェースでパラメータを設定するだけです。
Octoparse
WindowsとMac用の人気のあるビジュアルパーサー。タイムアウトとリトライの設定:
- タスク設定を開く → 高度なオプション
- ページ読み込みタイムアウト: 20-30秒に設定
- Ajaxタイムアウト: 動的コンテンツ用に10-15秒
- エラー時のリトライ回数: 3-5回
- プロキシ設定でリストをアップロードし、自動ローテーションを有効にできます
ParseHub
無料プランのクラウドパーサー。設定:
- 設定 → 高度な設定 → ページ読み込み遅延: 5-10秒
- リクエストタイムアウト: 30秒
- 失敗したリクエストをリトライ: 有効にして3回の試行
- プロジェクト設定を介してプロキシをサポート
Apify
人気のあるサイトをパーシングするための既製のアクター(スクリプト)を持つウェブタスク自動化プラットフォーム。多くのマーケットプレイス(Wildberries、Ozon)のパーシング用アクターには、最適なタイムアウトとリトライ設定が組み込まれています。あなたがする必要があるのは:
- 必要なサイトの既製アクターを選択
- プロキシを指定(プロキシプロバイダーとの統合をサポート)
- タスクを開始 — 残りは自動的に設定されます
アンチデテクトブラウザによる自動化
Dolphin Anty、AdsPower、またはMultiloginを介してソーシャルメディアや広告プラットフォームで作業している場合、タイムアウトはブラウザプロファイルで設定されます:
- Dolphin Anty: プロファイル設定 → プロキシ → タイムアウト: 10-15秒
- AdsPower: プロキシ設定 → 接続タイムアウト: 10秒、読み取りタイムアウト: 20秒
- Multilogin: ブラウザプロファイル → ネットワーク → プロキシタイムアウト: 15秒
これらのブラウザを介して自動化する場合(例えば、Seleniumスクリプトを使用する場合)、プロキシのタイムアウトはプロファイル設定から継承されますが、スクリプトレベルで追加のタイムアウトを設定することもできます。
タイムアウト設定時の一般的な間違い
経験豊富な開発者やパーシングの専門家でさえ、タイムアウトやリトライに関して一般的な間違いを犯すことがあります。以下は最も一般的なものです:
エラー1: タイムアウトがまったくない
多くのライブラリはデフォルトでタイムアウトを設定しないか、非常に大きな値(数分)を設定します。明示的にタイムアウトを指定しない場合、スクリプトは長時間ハングする可能性があります。
解決策: 各リクエストでタイムアウトを明示的に指定してください。15秒でエラーを取得する方が、5分待つよりも良いです。
エラー2: すべてのリトライで同じプロキシを使用する
プロキシが最初の試行で応答しなかった場合、同じプロキシで再試行する成功の可能性は非常に低いです。多くの人が試行の間にプロキシをローテーションすることを忘れます。
解決策: 各リトライでプールから新しいプロキシを使用してください。これは高い成功率にとって非常に重要です。
エラー3: 遅いプロキシに対して短すぎるタイムアウト
モバイルや一部の住宅プロキシはデータセンターよりも遅い場合があります。モバイルプロキシに5秒のタイムアウトを設定すると、十分に動作しているIPで多くの偽のエラーが発生します。
解決策: プロキシの種類を考慮してください。モバイル用には最低でも10-15秒のタイムアウトを使用してください。
エラー4: 無制限のリトライ
一部の人は、試行回数を制限せずにwhile Trueループでリトライを実装します。ターゲットサイト側に問題がある場合(例えば、完全にダウンしている場合)、スクリプトは無限に試行を続けます。
解決策: リトライの回数を常に制限してください(最大3-10回の試行)し、失敗したリクエストを後で分析するためにログに記録してください。
エラー5: エラータイプの無視
すべてのエラーを再試行する必要はありません。例えば、404(ページが見つかりません)を受け取った場合、再試行は無意味です。ページは存在しません。しかし、503(サービスが一時的に利用できません)は、数秒後に再試行する価値があります。
解決策: エラーのタイプを分析し、一時的な問題(タイムアウト、接続エラー、429、500、502、503、504)のみを再試行してください。
エラー6: ロギングの欠如
ログがなければ、リクエストが失敗する理由を理解できません: プロキシに問題があるのか、タイムアウトに問題があるのか、ターゲットサイトに問題があるのか?
解決策: 使用したプロキシ、タイムアウト、試行回数、発生したエラーの種類を示すすべてのエラーをログに記録してください。これにより、設定を最適化できます。
プロキシ選択のアドバイス: 正しい設定でもタイムアウトエラーが頻繁に発生する場合、プロキシの質に問題がある可能性があります。安価な公開プロキシや共有プロキシは、過負荷になり、遅く応答することがよくあります。安定した動作のために、保証された稼働時間を持つ質の高い住宅プロキシの使用をお勧めします。
結論
タイムアウトとリトライロジックの正しい設定は、単なる技術的な詳細ではなく、プロキシとの安定性と効率性にとって非常に重要な要素です。タイムアウトがなければ、スクリプトは死んだプロキシでハングし、時間を失います。リトライロジックがなければ、一時的なエラーでデータを失います。そして、再試行時にプロキシをローテーションしなければ、質の高いIPプールを持っていても低い成功率を得ることになります。
このガイドからの主な結論は次のとおりです:
- 常にタイムアウトを明示的に設定してください: connect timeout 5-10秒、read timeout 10-30秒はタスクに応じて設定します
- リトライロジックを使用し、3-5回の試行と指数的な遅延を設定してください
- 各再試行時にプロキシをローテーションしてください — これは高い成功率の鍵です
- 一時的なエラー(タイムアウト、429、500、502、503、504)のみを再試行し、永続的なエラー(404、403)には試行を無駄にしないでください
- すべてのエラーを分析し、設定を最適化するためにログに記録してください
- プロキシの種類を考慮してください: モバイルはデータセンターよりも遅く、タイムアウトをそれに応じて増やしてください
マーケットプレイス(Wildberries、Ozon、Avito)のパーシング、ソーシャルメディアの自動化、または広告プラットフォームで作業する場合、プロキシの安定性は直接的に結果に影響します。高い稼働時間を持つ質の高いプロキシを使用し、タイムアウトとリトライを正しく設定することで、時間を数時間節約し、数千のリクエストを失うことを避けることができます。
最大の安定性と最小限のタイムアウトエラーを必要とするタスクには、データセンタープロキシを試してみることをお勧めします — 高速な応答と安定した接続を提供し、大量のパーシングや自動化に特に重要です。