mcpField
S
scrapfly-scraper

scrapfly-scraper

github.com/scrapflyデータ・データベース5257 回インストール2 週間前に更新
リポジトリ

scrapfly-scraper について

scrapfly-scraperは、Scrapfly Scraper APIでウェブページやAPIのデータを収集するPythonスキルです。動的ページ、プロキシ、ボット対策への対応が必要な収集作業に向けて、複数の出力形式、ブラウザー操作、セッション再利用を備えています。

主な機能

  1. 01プロキシローテーションと地域指定
  2. 02ボット対策の回避とJavaScript描画
  3. 03ブラウザー操作シナリオの実行
  4. 04HTML、JSON、Markdown、テキスト出力
  5. 05セッション再利用とレスポンスキャッシュ

活用シーン

  1. 01ボット対策のあるサイトからコンテンツを収集
  2. 02JavaScript描画が必要なページをスクレイピング
  3. 03ログインやクリック、フォーム入力後に収集
  4. 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 のパラメーター
パラメーター型デフォルト説明
urlstr必須スクレイピング対象の URL
methodstr"GET"HTTP メソッド:GET、POST、PUT、PATCH、HEAD、OPTIONS
headersdictNoneカスタム HTTP ヘッダー
cookiesdictNoneカスタム Cookie(headers["cookie"] に統合されます)
bodystrNonePOST/PUT/PATCH 用の生のリクエストボディ。ペイロードを事前にエンコードした場合に使用します
datadictNonePOST/PUT/PATCH 用のフォーム/JSON データ。body が指定されていない場合、Content-Type に応じてエンコードされます
timeoutintNoneリクエストのタイムアウト(ミリ秒、デフォルトは約 150,000 ミリ秒)
retryboolTrueネットワーク障害時に自動で再試行します
countrystrNoneプロキシの国(ISO 3166-1 alpha-2。例:"us"、"de")
proxy_poolstrNoneプロキシプール:"basic"(データセンタープロキシ、Unblocker は無効、1 クレジット)、"unblocker"(住宅用プロキシと Unblocker のアンチボット回避機能、25 クレジット)、"unblocker_ultra"(同じ機能を備え、独自の料金が設定されたターゲットまたはアンチボット保護に対応する唯一のプール。その料金が加算されます)、または "auto"(API がターゲットのプロファイルに基づいてリクエスト前にプールを選択します。データセンタープロキシでの Unblocker、またはターゲットが必要とするプールのいずれかです。unblocker_ultra が必要なターゲットを含むすべてのターゲットで使用でき、その場合は料金が加算されます。実際に使用されるプールの料金が適用されます)。各プールで Unblocker の設定も行います。未設定の場合、SDK は proxy_pool を送信しません。プロキシプール導入前に記述されたリクエスト(非推奨のプール名 "public_datacenter_pool" と "public_residential_pool" を含む)については、移行ガイドを参照してください
sessionstrNoneリクエスト間で Cookie/フィンガープリントを保持するセッション ID
session_sticky_proxyboolTrue指定した session で同じプロキシ IP を維持します。"unblocker"、"unblocker_ultra"、"auto" では False は拒否されます
unblockerboolFalse非推奨:proxy_pool を使用してください(Unblocker には "unblocker_ultra")。プロキシプール導入前に記述されたリクエストについては、移行ガイドを参照してください。別名は asp です。両方が指定された場合は asp が優先されます
render_jsboolFalseヘッドレスブラウザーでの JavaScript レンダリングを有効にします(+5 クレジット)
rendering_waitintNoneページ読み込み後の待機時間(ミリ秒、render_js=True が必要です)
rendering_stagestr"complete"ブラウザーの準備完了ステージ:"complete" または "domcontentloaded"(render_js=True が必要です)
wait_for_selectorstrNone待機する CSS/XPath セレクター(render_js=True が必要です)
jsstrNoneブラウザーで実行する JavaScript コード(自動でエンコードされます)
js_scenariolistNoneブラウザー操作のリスト(クリック、入力、スクロール、待機など)
auto_scrollboolNone遅延読み込みコンテンツを取得するため、レンダリング中にページを自動スクロールします(render_js=True が必要です)
screenshotsdictNoneスクリーンショットを撮影します:{"fullpage": "png"} または {"selector": ".element"}(render_js=True が必要です)
screenshot_flagslist[str]Noneスクリーンショットのオプション:"load_images"、"dark_mode"、"block_banners"、"high_quality"、"print_media_format"
formatstr"raw"出力形式:"raw"、"clean_html"、"json"、"markdown"、"text"
format_optionslist[str]None形式の修飾子(Markdown のみ):"no_images"、"no_links"、"only_content"
extractdictNoneレスポンスに適用する生の抽出仕様(エンコードされ、extract として送信されます)
extraction_templatestrNone保存済みのサーバー側抽出テンプレートの名前
extraction_ephemeral_templatedictNone1 回だけ使用するインライン JSON 抽出テンプレート(ephemeral:)
extraction_promptstrNoneExtraction API 用の自然言語の指示
extraction_modelstrNoneExtraction API で使用する LLM モデル名
cacheboolFalseレスポンスのキャッシュを有効にします
cache_ttlintNoneキャッシュの有効期間(秒)
cache_clearboolFalsecache=True の場合、既存のキャッシュ済みレスポンスを消去します
dnsboolFalseDNS レコードと所要時間を result.dns に収集します(処理が遅くなります)
sslboolFalseSSL 証明書の詳細を result.ssl に収集します(処理が遅くなります)
debugboolFalseデバッグ記録と追加メタデータを有効にします
raise_on_upstream_errorboolTrue上流からの 4xx/5xx HTTP レスポンスに対して例外を発生させます
correlation_idstrNoneシステム間でリクエストを追跡するカスタム ID
tagslist[str]Noneリクエストの整理と分析に使用するカスタムタグ
langlist[str]NoneAccept-Language の値。例:["en-US", "en"]
osstrNoneブラウザーの OS フィンガープリントを上書きします。例:"windows"、"macos"
webhookstrNone非同期スクレイピング完了時のコールバックに使用する名前付き Webhook
cost_budgetintNoneunblocker、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 メソッドはレート制限を自動的に処理します

コメント