scraperapi-async について
ScraperAPIでスクレイピングジョブをバックグラウンド送信する方法をまとめたスキルです。大量のURLや応答の遅い対象向けに、バッチ送信、再試行、状態確認、Webhook配信を扱います。
主な機能
- 01単一・バッチジョブの送信
- 02最大50,000件のURLを一括処理
- 03ポーリングまたはWebhookで結果取得
- 04最大24時間のジョブ再試行
- 05PDFや画像のレスポンス処理
活用シーン
- 01多数のURLの非同期スクレイピング
- 02Webhookによる完了結果の受信
- 03PDFなどバイナリデータの収集
- 04メタデータによるバッチ追跡
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ scraperapi/ scraperapi-skills --skill scraperapi-asyncインストール後、Claude Code で/scraperapi-asyncを入力して読み込まれたか確認します。
詳細
ScraperAPI Async Jobs API
Async API はスクレイピングジョブをバックグラウンドで送信し、成功率を最大化するために最大 24 時間再試行します。結果はステータス URL をポーリングして取得するか、Webhook で自動的に受信します。
Async を使用しないケース
- 単一の URL で、結果がすぐに必要な場合 → Standard API(
api.scraperapi.com)を使用してください。よりシンプルで、結果がインラインで返されます。 - サイト内のリンクをたどる必要がある場合 → Crawler を使用してください。
- 定期的にスケジュールされたスクレイピングが必要な場合 → DataPipeline を使用してください。
次の場合は Async を使用してください。20 件以上の URL をスクレイピングする場合、対象サイトの応答が遅い、または不安定な場合、Webhook による配信を希望する場合、PDF や画像をスクレイピングする必要がある場合。
エンドポイント
| 操作 | メソッド | URL |
|---|---|---|
| 単一ジョブを送信 | POST | https://async.scraperapi.com/jobs |
| バッチを送信(最大 50k) | POST | https://async.scraperapi.com/batchjobs |
| ジョブを確認/取得 | GET | https://async.scraperapi.com/jobs/<jobId> |
| ジョブをキャンセル | DELETE | https://async.scraperapi.com/jobs/<jobId> |
認証:JSON リクエスト本文の apiKey(注:apiKey はキャメルケースです。Standard API の api_key とは異なります)。
単一ジョブ
import os, requests, time
API_KEY = os.environ["SCRAPERAPI_API_KEY"]
# Submit
r = requests.post(
"https://async.scraperapi.com/jobs",
json={
"apiKey": API_KEY,
"url": "https://example.com/product/123",
"apiParams": {
"render": True,
"country_code": "us",
}
}
)
job = r.json()
# {"id": "...", "status": "running", "statusUrl": "...", "url": "..."}
# Poll
def poll(status_url, interval=5, max_wait=120):
deadline = time.time() + max_wait
while time.time() < deadline:
data = requests.get(status_url).json()
if data["status"] == "finished":
return data["response"]["body"]
if data["status"] == "failed":
raise RuntimeError(f"Job failed: {data.get('failReason')}")
time.sleep(interval)
raise TimeoutError("Job did not finish in time")
html = poll(job["statusUrl"])
完了したジョブのレスポンス形式:
{
"id": "...",
"status": "finished",
"statusUrl": "...",
"url": "https://example.com/product/123",
"response": {
"headers": { "content-type": "text/html", "sa-final-url": "...", "sa-statuscode": "200" },
"body": "<!doctype html>...",
"statusCode": 200
}
}
バッチジョブ(最大 50,000 件の URL)
jobs = requests.post(
"https://async.scraperapi.com/batchjobs",
json={
"apiKey": API_KEY,
"urls": [
"https://example.com/page/1",
"https://example.com/page/2",
# ... up to 50,000
],
"apiParams": {"country_code": "us"}
}
).json()
# Returns a list of {id, status, statusUrl, url} — one per submitted URL
results = [poll(job["statusUrl"]) for job in jobs]
50,000 件を超える URL を処理する場合は、複数のバッチリクエストに分割してください。バッチが大きい場合はポーリングの代わりに、以下の Webhook を使用してください。10,000 件のステータス URL を順番にポーリングすると時間がかかります。
Webhook コールバック
ポーリングせずに結果を受信するには、Webhook を使用してください。スクレイピングが完了すると、ScraperAPI は完了したジョブのペイロードを URL に POST します。
requests.post(
"https://async.scraperapi.com/jobs",
json={
"apiKey": API_KEY,
"url": "https://example.com/",
"callback": {
"type": "webhook",
"url": "https://yourapp.com/scraperapi/callback"
}
}
)
Webhook の仕組み:
- デフォルトでは、成功したジョブのみがコールバックをトリガーします。
- 失敗したジョブのペイロードも受信するには、
"expectUnsuccessReport": trueを設定します。 - ScraperAPI は配信を 3 回再試行します。すべて失敗した場合、ジョブはキャンセルされます。
- Webhook URL は一般にアクセス可能である必要があります。
- サーバーなしでテストするには、webhook.site を使用してください。
失敗したジョブのコールバックペイロード:
{
"id": "...",
"attempts": 50,
"status": "failed",
"failReason": "failed_due_to_timeout",
"url": "https://example.com/"
}
すべてのリクエスト本文パラメーター
{
"apiKey": "YOUR_KEY",
"url": "https://example.com",
"urls": ["url1", "url2"],
"method": "GET",
"headers": { "Accept-Language": "en-US" },
"body": "foo=bar",
"callback": { "type": "webhook", "url": "https://..." },
"expectUnsuccessReport": false,
"timeoutSec": 600,
"meta": { "jobLabel": "batch-42" },
"apiParams": {
"autoparse": false,
"country_code": "us",
"keep_headers": false,
"device_type": "desktop",
"follow_redirect": true,
"premium": false,
"ultra_premium": false,
"render": false,
"wait_for_selector": ".content",
"screenshot": false,
"retry_404": false,
"output_format": "html",
"max_cost": 10
}
}
Async 専用パラメーター
| パラメーター | 型 | 用途 |
|---|---|---|
expectUnsuccessReport | boolean | 失敗したジョブの Webhook ペイロードも受信する |
timeoutSec | integer | デフォルトのジョブタイムアウト(秒)を上書きする |
meta | object | カスタムメタデータ。照合用に、すべてのレスポンス/コールバックでそのまま返されます |
meta は、ジョブがどのバッチまたはワークフローに属するかを追跡するのに特に便利です。
{ "meta": { "batchId": "run-2024-06", "sourceFile": "urls.csv" } }
対象サイトへの POST リクエストの送信
requests.post(
"https://async.scraperapi.com/jobs",
json={
"apiKey": API_KEY,
"url": "https://api.example.com/search",
"method": "POST",
"headers": {"content-type": "application/x-www-form-urlencoded"},
"body": "query=scraperapi&page=1",
}
)
バイナリレスポンス(PDF と画像)
対象 URL がバイナリコンテンツを返す場合、レスポンス本文は response.base64EncodedBody 内で Base64 エンコードされます。
import base64
r = requests.post(
"https://async.scraperapi.com/jobs",
json={"apiKey": API_KEY, "url": "https://example.com/report.pdf"}
)
job = r.json()
# ... wait or poll ...
result = requests.get(job["statusUrl"]).json()
pdf_bytes = base64.b64decode(result["response"]["base64EncodedBody"])
with open("report.pdf", "wb") as f:
f.write(pdf_bytes)
保持ポリシー
ジョブの結果は、ジョブ完了後最大 72 時間(24 時間は保証)保存されます。その後データは削除されるため、再度必要な場合はジョブを再送信してください。
保持期間が終了する前に結果を取得してください。長時間のパイプラインでは、完了時に結果がシステムへすぐにプッシュされるよう、Webhook の使用をおすすめします。
エラー処理
| ステータス | 意味 | 対応 |
|---|---|---|
ジョブが finished、statusCode: 200 | 成功 | response.body を使用する |
ジョブが finished、statusCode: 403 | 対象サイトがスクレイピングをブロックした | apiParams に premium: true を指定して再試行する |
ジョブが failed、failReason: failed_due_to_timeout | 24 時間の再試行後にタイムアウトした | 対象サイトにアクセスできるか確認し、render: false を試す |
| 送信時の HTTP 401 | API キーが無効 | SCRAPERAPI_API_KEY を確認する |
| 送信時の HTTP 403 | クレジット不足、またはプランの上限に達した | ダッシュボードを確認する |
| 送信時の HTTP 429 | 同時送信数が多すぎる | 間隔を空けて、バッチに分けて再送信する |
リクエストごとのクレジット消費を制限するには、apiParams で max_cost を使用してください。上限を超えるリクエストは、想定以上のクレジットを消費する代わりに 403 を返します。
クレジット料金
Async API のクレジット料金は Standard API と同じです:
| リクエストタイプ | クレジット |
|---|---|
| 標準 | 1 |
render: true | 10 |
premium: true | 10 |
ultra_premium: true | 30 |
| 失敗したリクエスト | 0 |
すべての再試行を使い切った後に失敗した非同期ジョブには、課金されません。