scrapfly-scraper について
scrapfly-scraperは、Scrapfly Scraper APIでウェブページやAPIのデータを収集するPythonスキルです。動的ページ、プロキシ、ボット対策への対応が必要な収集作業に向けて、複数の出力形式、ブラウザー操作、セッション再利用を備えています。
主な機能
- 01プロキシローテーションと地域指定
- 02ボット対策の回避とJavaScript描画
- 03ブラウザー操作シナリオの実行
- 04HTML、JSON、Markdown、テキスト出力
- 05セッション再利用とレスポンスキャッシュ
活用シーン
- 01ボット対策のあるサイトからコンテンツを収集
- 02JavaScript描画が必要なページをスクレイピング
- 03ログインやクリック、フォーム入力後に収集
- 04国を指定したプロキシ経由でデータを収集
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ scrapfly/ skills --skill scrapfly-scraperインストール後、Claude Code で/scrapfly-scraperを入力して読み込まれたか確認します。
詳細
Scrapfly スクレイパー
Scrapfly Scraper API を使用して、プロキシローテーション、ボット対策の回避、JavaScript のレンダリング、ブラウザー制御用の JavaScript シナリオにより、Web ページのデータを収集します。
使用する場面
- Web ページ(HTML、JSON、テキスト、Markdown)のスクレイピング
- ボット対策(Cloudflare、DataDome、PerimeterX、Kasada など)の回避
- ジオターゲティングを使ったローテーションプロキシ経由でのデータ収集
- ヘッドレスブラウザーでの JavaScript を多用したページのレンダリング
- よく使う操作(セレクターの待機、クリック、要素への入力など)を行う JavaScript シナリオによるブラウザー制御
- セッションを再利用したスクレイピング
- ブラウザーの XHR 呼び出しデータの取得
セットアップ
pip install scrapfly-sdk
API キーは、環境変数 SCRAPFLY_API_KEY を使って指定するか、クライアントに直接渡す必要があります。
API リファレンス
エンドポイント: https://api.scrapfly.io/scrape
HTTP メソッドは上流の URL に転送されます。
Web ページまたは API からデータを取得するには、デフォルトの GET メソッドを使用します。
API リソースで POST などの別のメソッドが必要な場合は、ScrapeConfig の method パラメーターで指定できます。
ScrapflyClient
from scrapfly import ScrapflyClient, ScrapeConfig, ScrapeApiResponse
import os
client = ScrapflyClient(key=os.environ["SCRAPFLY_API_KEY"])
ScrapeConfig のパラメーター
| パラメーター | 型 | デフォルト | 説明 |
|---|---|---|---|
url | str | 必須 | スクレイピング対象の URL |
method | str | "GET" | HTTP メソッド:GET、POST、PUT、PATCH、HEAD、OPTIONS |
headers | dict | None | カスタム HTTP ヘッダー |
cookies | dict | None | カスタム Cookie(headers["cookie"] に統合されます) |
body | str | None | POST/PUT/PATCH 用の生のリクエストボディ。ペイロードを事前にエンコードした場合に使用します |
data | dict | None | POST/PUT/PATCH 用のフォーム/JSON データ。body が指定されていない場合、Content-Type に応じてエンコードされます |
timeout | int | None | リクエストのタイムアウト(ミリ秒、デフォルトは約 150,000 ミリ秒) |
retry | bool | True | ネットワーク障害時に自動で再試行します |
country | str | None | プロキシの国(ISO 3166-1 alpha-2。例:"us"、"de") |
proxy_pool | str | None | プロキシプール:"basic"(データセンタープロキシ、Unblocker は無効、1 クレジット)、"unblocker"(住宅用プロキシと Unblocker のアンチボット回避機能、25 クレジット)、"unblocker_ultra"(同じ機能を備え、独自の料金が設定されたターゲットまたはアンチボット保護に対応する唯一のプール。その料金が加算されます)、または "auto"(API がターゲットのプロファイルに基づいてリクエスト前にプールを選択します。データセンタープロキシでの Unblocker、またはターゲットが必要とするプールのいずれかです。unblocker_ultra が必要なターゲットを含むすべてのターゲットで使用でき、その場合は料金が加算されます。実際に使用されるプールの料金が適用されます)。各プールで Unblocker の設定も行います。未設定の場合、SDK は proxy_pool を送信しません。プロキシプール導入前に記述されたリクエスト(非推奨のプール名 "public_datacenter_pool" と "public_residential_pool" を含む)については、移行ガイドを参照してください |
session | str | None | リクエスト間で Cookie/フィンガープリントを保持するセッション ID |
session_sticky_proxy | bool | True | 指定した session で同じプロキシ IP を維持します。"unblocker"、"unblocker_ultra"、"auto" では False は拒否されます |
unblocker | bool | False | 非推奨:proxy_pool を使用してください(Unblocker には "unblocker_ultra")。プロキシプール導入前に記述されたリクエストについては、移行ガイドを参照してください。別名は asp です。両方が指定された場合は asp が優先されます |
render_js | bool | False | ヘッドレスブラウザーでの JavaScript レンダリングを有効にします(+5 クレジット) |
rendering_wait | int | None | ページ読み込み後の待機時間(ミリ秒、render_js=True が必要です) |
rendering_stage | str | "complete" | ブラウザーの準備完了ステージ:"complete" または "domcontentloaded"(render_js=True が必要です) |
wait_for_selector | str | None | 待機する CSS/XPath セレクター(render_js=True が必要です) |
js | str | None | ブラウザーで実行する JavaScript コード(自動でエンコードされます) |
js_scenario | list | None | ブラウザー操作のリスト(クリック、入力、スクロール、待機など) |
auto_scroll | bool | None | 遅延読み込みコンテンツを取得するため、レンダリング中にページを自動スクロールします(render_js=True が必要です) |
screenshots | dict | None | スクリーンショットを撮影します:{"fullpage": "png"} または {"selector": ".element"}(render_js=True が必要です) |
screenshot_flags | list[str] | None | スクリーンショットのオプション:"load_images"、"dark_mode"、"block_banners"、"high_quality"、"print_media_format" |
format | str | "raw" | 出力形式:"raw"、"clean_html"、"json"、"markdown"、"text" |
format_options | list[str] | None | 形式の修飾子(Markdown のみ):"no_images"、"no_links"、"only_content" |
extract | dict | None | レスポンスに適用する生の抽出仕様(エンコードされ、extract として送信されます) |
extraction_template | str | None | 保存済みのサーバー側抽出テンプレートの名前 |
extraction_ephemeral_template | dict | None | 1 回だけ使用するインライン JSON 抽出テンプレート(ephemeral:) |
extraction_prompt | str | None | Extraction API 用の自然言語の指示 |
extraction_model | str | None | Extraction API で使用する LLM モデル名 |
cache | bool | False | レスポンスのキャッシュを有効にします |
cache_ttl | int | None | キャッシュの有効期間(秒) |
cache_clear | bool | False | cache=True の場合、既存のキャッシュ済みレスポンスを消去します |
dns | bool | False | DNS レコードと所要時間を result.dns に収集します(処理が遅くなります) |
ssl | bool | False | SSL 証明書の詳細を result.ssl に収集します(処理が遅くなります) |
debug | bool | False | デバッグ記録と追加メタデータを有効にします |
raise_on_upstream_error | bool | True | 上流からの 4xx/5xx HTTP レスポンスに対して例外を発生させます |
correlation_id | str | None | システム間でリクエストを追跡するカスタム ID |
tags | list[str] | None | リクエストの整理と分析に使用するカスタムタグ |
lang | list[str] | None | Accept-Language の値。例:["en-US", "en"] |
os | str | None | ブラウザーの OS フィンガープリントを上書きします。例:"windows"、"macos" |
webhook | str | None | 非同期スクレイピング完了時のコールバックに使用する名前付き Webhook |
cost_budget | int | None | unblocker、unblocker_ultra、auto プールで、Unblocker がリクエストに使用できる最大クレジット数 |
ScrapeApiResponse
response = client.scrape(ScrapeConfig(url="https://httpbin.dev"))
response.content # Page content (HTML/JSON/text)
response.scrape_result # Full result dict
response.status_code # Scrapfly API HTTP status code
response.scrape_result["status_code"] # Upsteam HTTP status code
response.headers # Response headers
response.context # Metadata about features used
例
基本的なスクレイピング
from scrapfly import ScrapflyClient, ScrapeConfig
import os
client = ScrapflyClient(key=os.environ["SCRAPFLY_API_KEY"])
result = client.scrape(ScrapeConfig(
url="https://httpbin.dev",
))
print(result.content)
ボット対策の回避と地域ターゲティングを使用したスクレイピング
result = client.scrape(ScrapeConfig(
url="https://httpbin.dev",
proxy_pool="unblocker", # residential proxies and the Unblocker to bypass antibots
country="us", # match the proxy with the domain country
))
JavaScript レンダリングを使用したスクレイピング
result = client.scrape(ScrapeConfig(
url="https://web-scraping.dev/products",
render_js=True, # enable JavaScript rendering using a cloud browser
rendering_wait=5000, # rendering wait for wait for
wait_for_selector="div.product", # wait a for a selector to be present on the page
))
Markdown 形式でのスクレイピング
result = client.scrape(ScrapeConfig(
url="https://web-scraping.dev/products",
format="markdown", # other supported formats are: json, text, clean_html
))
print(result.content)
body を使用した POST リクエスト
result = client.scrape(ScrapeConfig(
url="https://httpbin.dev/anything",
method="POST",
headers={"Content-Type": "application/json"},
body='{"query": "search term"}',
))
print(result.content)
JavaScript シナリオ(ブラウザー操作)
result = client.scrape(ScrapeConfig(
url="https://web-scraping.dev/login",
render_js=True,
# browser control
js_scenario=[
{
"fill":{
"selector":"input[name='username']","clear":True,"value":"user123"
}
},{
"fill":{
"selector":"input[name='password']","clear":True,"value":"password"
}
},{
"click":{
"selector":"form > button[type='submit']"
}
},{
"wait_for_navigation":{
"timeout":5000
}
}
],
# request headers
headers={
"cookie":"cookiesAccepted=true"
}
))
# access the element under login
print(result.selector.css("div#secret-message::text").get())
組み込みの Parsel セレクター
result = client.scrape(ScrapeConfig(
url="https://web-scraping.dev/products",
render_js=True
))
# access the built-in Parsel selector
selector = result.selector
for product in selector.css("div.product"):
print("product name:", product.xpath(".//a/text()").get()) # using xpath
print("product price:", product.css("div.price::text").get()) # using css
並行スクレイピング
import asyncio
from scrapfly import ScrapflyClient, ScrapeConfig
client = ScrapflyClient(key=os.environ["SCRAPFLY_API_KEY"])
urls = [
"https://web-scraping.dev/products",
"https://web-scraping.dev/products?page=2",
"https://web-scraping.dev/products?page=3",
]
configs = [ScrapeConfig(url=url) for url in urls]
async def concurrent_scraping():
results = []
async for result in client.concurrent_scrape(configs):
results.append(result)
for result in results:
print(result.content[:100])
print("===========")
asyncio.run(concurrent_scraping())
セッションを使用した状態を維持するスクレイピング
# First request: login
result = client.scrape(ScrapeConfig(
url="https://web-scraping.dev/login",
render_js=True,
# browser control
js_scenario=[
{
"fill":{
"selector":"input[name='username']","clear":True,"value":"user123"
}
},{
"fill":{
"selector":"input[name='password']","clear":True,"value":"password"
}
},{
"click":{
"selector":"form > button[type='submit']"
}
},{
"wait_for_navigation":{
"timeout":5000
}
}
],
# request headers
headers={
"cookie":"cookiesAccepted=true"
},
session="logged-in-session"
))
# Second request: access protected page with same session
result = client.scrape(ScrapeConfig(
url="https://web-scraping.dev/login",
session="logged-in-session"
))
# access the built-in selector
print(result.selector.css("div#secret-message::text").get())
レスポンスのキャッシュ
result = client.scrape(ScrapeConfig(
url="https://example.com",
cache=True,
cache_ttl=3600, # Cache for 1 hour
))
エラー処理
from scrapfly import ScrapflyClient, ScrapeConfig
from scrapfly.errors import (
ScrapflyError,
UpstreamHttpClientError,
UpstreamHttpServerError,
ScrapflyProxyError,
ScrapflyThrottleError,
)
try:
result = client.scrape(ScrapeConfig(url="https://httpbin.dev", proxy_pool="unblocker"))
except ScrapflyThrottleError as e:
print(f"Rate limited, retry after {e.retry_delay}s")
except UpstreamHttpClientError as e:
print(f"Target returned 4xx: {e.message}")
except UpstreamHttpServerError as e:
print(f"Target returned 5xx: {e.message}")
except ScrapflyProxyError as e:
print(f"Proxy error: {e.message}")
except ScrapflyError as e:
print(f"Scrapfly error: {e.message}")
独自の料金が発生するターゲット、またはボット対策には、proxy_pool="unblocker_ultra" と "auto" を指定できます。これらを指定すると、その料金が加算されます。basic と unblocker では ERR::PROXY::UNBLOCKER_ULTRA_REQUIRED が返されます(HTTP 422、課金対象外)。再送信するには、unblocker_ultra を指定します。
try:
result = client.scrape(ScrapeConfig(url=url, proxy_pool="unblocker"))
except ScrapflyError as e:
if e.code != "ERR::PROXY::UNBLOCKER_ULTRA_REQUIRED":
raise
result = client.scrape(ScrapeConfig(url=url, proxy_pool="unblocker_ultra"))
重要な注意事項
rendering_wait、wait_for_selector、js、js_scenario、screenshotsにはrender_js=Trueが必要です- サイトに必要なプロキシプールを選択します。データセンタープロキシでアクセスできる場合は
"basic"、住宅用プロキシと Unblocker が必要な場合は"unblocker"、API がERR::PROXY::UNBLOCKER_ULTRA_REQUIREDを返す場合は"unblocker_ultra"を指定します。または、API にターゲットのプロファイルから選択させるには"auto"を指定します unblocker=Trueとそのエイリアスであるasp=Trueは非推奨です。代わりにproxy_poolを使用してください(Unblocker には"unblocker_ultra"を指定します)。移行ガイドでは、プロキシプール導入前に記述されたリクエストについて説明しています- LLM が利用しやすいクリーンなコンテンツを取得するには、
format="markdown"を使用してください - 複数のリクエスト間で状態を維持するには、
sessionパラメーターを使用してください concurrent_scrapeメソッドはレート制限を自動的に処理します