KYC不要 — IDもセルフィーも書類も不要。暗号通貨で支払い:BTC, USDT, USDC, ETH, SOL, LTC
言語: 日本語
今すぐ始める

ドキュメント · 同時実行 · スループット · エチケット

レジデンシャルプロキシによる同時実行数とスループット

ゲートウェイ課金はスレッドごとではなくGB単位で行われるため、実際の制限は各ターゲットサイトごとになります。必要なスループットから同時実行数を決め、ホストごとに上限を設定し、レスポンスを見て速度を調整してください。

最終更新:

クイックアンサー

レジデンシャルプロキシを使って同時にどれくらいのリクエストを実行できますか?

ターゲットごとに許容されるだけ実行可能です:CrawlRelayはスレッドや接続単位ではなくGB単位のレジデンシャルトラフィックに対して課金($0.50/GBは50 GBから)。Littleの法則で同時実行数を決めます。フライト中のリクエスト数=毎秒ページ数×ページあたり秒数、ホストごとに上限を設け、最初は2から4で始め、429や503のレスポンスが出たら減らしましょう。KYC不要で暗号通貨決済可能です。

同時実行の概要

課金トラフィックのGB単位で課金。スレッドや接続での課金なし
サイズ決定ルールフライト中 = スループット × レイテンシ(Littleの法則)
ホストごとの開始点2〜4の並列リクエスト、小規模サイトは1リクエストに遅延あり
速度を落とすサイン429, 503, レスポンス時間の上昇, チャレンジページ
帯域幅の計算毎秒ページ数 × ページあたりバイト数 × 3600 = 1時間あたりバイト数
レジデンシャルの中央値レスポンス時間プロキシネットワーク上で0.93秒、実際のターゲットでは3.21秒(Proxyway 2026)

必要なスループットから同時実行数をどう決める?

Littleの法則を使います:フライト中のリクエスト数は望むレートと各リクエストの処理時間の積。Proxywayの2026年調査によるとレジデンシャルプロキシ経由の実ターゲットで中央値は3.21秒。つまりネットワーク上の1秒未満の数字ではなく、実サイトの2〜4秒で計画しましょう。

目標リクエストあたり時間フライト中リクエスト数
5ページ/秒2秒10
20ページ/秒2秒40
20ページ/秒4秒80
100ページ/秒3秒300

これらのリクエストを複数ホストに分散してください。200サイトにまたがって40リクエストは適度ですが、小さいサイト1箇所に40リクエストは負荷テストであり、許可されていません。

そのスループットでどれくらいの帯域幅を使う?

毎秒ページ数にページあたりのバイト数をかけます。20ページ/秒で1ページ50KBなら、クロールは1MB/秒で3.6GB/時間、約86GB/日です。レンダリング後2MB/ページなら40MB/秒に。

計算結果にプランのGBあたり価格($0.50/GBは50 GBから、CrawlRelay)をかけて時間単位のコストを算出。バンド幅計算機のガイド](/guides/bandwidth-calculator/)には典型的なページサイズがタイプ別に記載されています。

ホストごとの制限はどれくらいから始めれば?

ターゲットホストごとの並列リクエスト数リクエスト間の遅延備考
小規模サイト(ブログ、地元ショップ)12–5秒robots.txt内のCrawl-delayを尊重してください
中規模サイト2–40.5〜2秒応答時間を監視し、倍増したら抑制する
CDNを備えた大規模プラットフォーム4–16AutoThrottleまたは適応型429や5xx率が安定している間のみ増加させる
パブリックAPIドキュメントに記載された制限ドキュメント通りプロバイダーが提供するAPIキーと制限を使用する

同時実行数を自動で適応させるには?

TCPが混雑制御に使うルール、加法的増加と乗法的減少を使います:正常な応答が続いたらスロットを1つ追加し、429や503が来たときに制限を半分にします。以下のリミッターはホストごとに1つの制限を保持し、そのホストへの全リクエストをRetry-After秒遅延させて一度リトライし、設定した上限を超えません。ネットワークエラーは値として返るため、1回のタイムアウトでバッチが停止しません。

Python asyncio: httpxによる適応制限
import asyncio
import random
from urllib.parse import urlsplit

import httpx

PROXY = "http://USERNAME-country-us:[email protected]:7777"


class AdaptiveLimit:
    """One per host: +1 slot after 20 clean responses, halve on 429/503, pause for Retry-After."""

    def __init__(self, start=2, low=1, high=16):
        self.limit, self.low, self.high = start, low, high
        self.in_flight, self.clean = 0, 0
        self.pause_until = 0.0
        self.cond = asyncio.Condition()

    async def __aenter__(self):
        loop = asyncio.get_running_loop()
        while True:
            async with self.cond:
                await self.cond.wait_for(lambda: self.in_flight < self.limit)
                delay = self.pause_until - loop.time()
                if delay <= 0:
                    self.in_flight += 1
                    return self
            await asyncio.sleep(delay)  # the host asked for a pause: wait outside the lock

    async def __aexit__(self, *exc):
        async with self.cond:
            self.in_flight -= 1
            self.cond.notify_all()

    def record(self, status, retry_after=None):
        if status in (429, 503):
            self.limit, self.clean = max(self.low, self.limit // 2), 0
            wait = int(retry_after) if retry_after and retry_after.isdigit() else 5 + random.random()
            now = asyncio.get_running_loop().time()
            self.pause_until = max(self.pause_until, now + wait)
        elif status < 400:
            self.clean += 1
            if self.clean >= 20 and self.limit < self.high:
                self.limit, self.clean = self.limit + 1, 0


gates = {}


def gate_for(url):
    host = urlsplit(url).hostname
    if host not in gates:
        gates[host] = AdaptiveLimit()
    return gates[host]


async def fetch(client, url, attempts=2):
    gate = gate_for(url)
    status = None
    for _ in range(attempts):
        try:
            async with gate:
                r = await client.get(url)
        except httpx.HTTPError as exc:
            return "error: %s" % type(exc).__name__
        status = r.status_code
        gate.record(status, r.headers.get("Retry-After"))
        if status not in (429, 503):
            break  # the retry, if any, waits for the host's pause in __aenter__
    return status


async def main(urls):
    timeout = httpx.Timeout(30.0, connect=10.0)
    async with httpx.AsyncClient(proxy=PROXY, timeout=timeout) as client:
        print(await asyncio.gather(*(fetch(client, u) for u in urls)))
    print({host: gate.limit for host, gate in gates.items()})


asyncio.run(main(["https://example.com/"] * 10))

ターゲット以外でプロキシ経由クロールを遅くする要因は?

  • TLSハンドシェイク。 新しいIPごとにリクエストごとに接続を張ると、毎回サイトとのハンドシェイクが発生します。IPの多様性が不要な同一サイトの複数ページでは、キープアライブでスティッキーセッションを維持しましょう。
  • 遅い出口。 レジデンシャルプロキシや4Gモバイルプロキシは実際の自宅や携帯回線です。タイムアウトを設定し、新しい接続でリトライしましょう。
  • 狭いターゲティング。 小規模都市や単一ASNは国全体より出口数が少ないです。データ変動がある場所だけを狙いましょう。
  • レンダリング。 ヘッドレスブラウザはHTTPクライアントよりもCPU、メモリ、トラフィックを大量に消費します。JavaScriptが必要なページだけレンダリングしましょう。
  • DNS。 socks5h://やHTTPポートでは出口でDNS解決されるため、ターゲットホスト向けにローカルリゾルバキャッシュは不要です。

同時実行に関する質問

CrawlRelayはスレッド数や接続数を制限しますか?

プランはスレッド、接続数、リクエスト数ではなくトラフィックのGB単位で課金され、公開されたプランはスレッド数制限を設けていません。実際の制限は各ターゲットの許容量と自身のマシン性能です。大規模クロールを計画するなら、まず[email protected]に連絡してターゲティングのカバレッジを確認しましょう。

スレッド数を増やしたらなぜクロールが遅くなった?

多くはターゲット側がスロットリングを始めたからです:応答時間が増加し、429や503が現れ、リトライが負荷を増やします。もう一つの原因は自身のマシンのCPUやソケット不足、特にヘッドレスブラウザ使用時です。スレッド追加前にホスト毎の遅延とエラー率を計測しましょう。

リクエストごとに接続する方がキープアライブより遅い?

はい。リクエストごとにTCPとTLSのハンドシェイクが入るため、通常レジデンシャルプロキシ経由で数百ミリ秒遅くなります。これがIPを毎回変える対価です。IPが重要でない同一サイトの複数ページでは、キープアライブのスティッキーセッションの方が高速でトラフィックも抑えられます。

同時クロールでrobots.txtのcrawl-delayを守るには?

ホストごとにrobots.txtを1回解析し、RFC 9309の推奨どおり最大24時間キャッシュし、Crawl-delay値は同時実行1でホストごとの最小リクエスト間隔に変換します。Pythonのurllib.robotparserはcrawl_delay()経由でこれを提供します。

GB単位料金でスケール

$0.50/GB を 50 GB から 1 TB へ、期限切れしないトラフィック。

$0.50/GBから · KYC不要

今すぐ始める