mcpField
P
python-sdk-best-practices

python-sdk-best-practices

github.com/brightdata開発26847 回インストール2 週間前に更新
リポジトリ

python-sdk-best-practices について

Bright Data SDK を使う Python コードを作成するコーディングエージェント向けのベストプラクティススキルです。クライアントのライフサイクル、非同期・同期処理、スクレイピング、検索、データセット、ブラウザー利用、エラー処理を扱います。

主な機能

  1. 01非同期・同期クライアントの使い方
  2. 02ウェブとプラットフォームのスクレイピング
  3. 03SERP 検索とデータセットの説明
  4. 04ブラウザーとカスタムスクレイパーの利用
  5. 05ライフサイクルとエラー処理の指針

活用シーン

  1. 01非同期 Python のスクレイピングコード作成
  2. 02スクリプト向け同期クライアントの選択
  3. 03検索結果やデータセットレコードの取得
  4. 04長時間実行するスクレイパージョブの管理

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/brightdata/skills --skill python-sdk-best-practices

インストール後、Claude Code で/python-sdk-best-practicesを入力して読み込まれたか確認します。

同梱ファイルreferences/api-reference.md

詳細

Bright Data Python SDK - コーディングエージェント向けベストプラクティス

brightdata-sdk Python パッケージを使用するコードを作成する際は、以下のルールに厳密に従ってください。

インストール

pip install brightdata-sdk

重要なルール

  1. 必ずコンテキストマネージャーを使用してください。 クライアントは必ず async with(同期の場合は with)で使用してください。これを忘れると、RuntimeError: BrightDataClient not initialized が発生します。
  2. 非同期がデフォルトです。 メインのクライアントは BrightDataClient(非同期)です。非同期を使用できない場合に限り、SyncBrightDataClient を使用してください。
  3. 非同期関数内で SyncBrightDataClient を使用しないでください。 RuntimeError が発生します。代わりに BrightDataClient を使用してください。
  4. トークンは環境変数から自動的に読み込まれます。 BRIGHTDATA_API_TOKEN 環境変数を設定するか、token= パラメーターを渡してください。トークンをコードにハードコードしないでください。
  5. スクレイパーのすべてのメソッドは await 可能です。 非同期クライアントへの呼び出しはすべて await してください。

認証

# Option 1: Environment variable (preferred)
# export BRIGHTDATA_API_TOKEN="your_token"
async with BrightDataClient() as client:
    ...

# Option 2: Explicit token
async with BrightDataClient(token="your_token") as client:
    ...

# Option 3: .env file (requires python-dotenv)
# BRIGHTDATA_API_TOKEN=your_token
async with BrightDataClient() as client:
    ...

インポート

# Main clients
from brightdata import BrightDataClient          # Async (primary)
from brightdata import SyncBrightDataClient       # Sync wrapper

# Result models
from brightdata import ScrapeResult, SearchResult, CrawlResult

# Job model (for manual trigger/poll/fetch)
from brightdata import ScrapeJob

# Exceptions
from brightdata import (
    BrightDataError,       # Base exception
    ValidationError,       # Invalid input
    AuthenticationError,   # Bad/missing token
    APIError,              # API request failed (has .status_code, .response_text)
    ZoneError,             # Zone operation failed
    NetworkError,          # Network issue
    SSLError,              # SSL cert error
)

# Scraper Studio
from brightdata import ScraperStudioJob, JobStatus

# Dataset export utility
from brightdata.datasets import export

基本パターン

パターン 1:ウェブスクレイピング(Web Unlocker)

Bright Data のプロキシネットワーク経由で任意の URL をスクレイピングし、ボット検出を回避します。

import asyncio
from brightdata import BrightDataClient

async def main():
    async with BrightDataClient() as client:
        # Single URL - returns ScrapeResult
        result = await client.scrape_url("https://example.com")
        print(result.success)  # bool
        print(result.data)     # HTML string or parsed data
        print(result.cost)     # float, USD

        # With options
        result = await client.scrape_url(
            url="https://example.com",
            country="us",              # Proxy country
            response_format="raw",     # "raw" (HTML) or "json"
            method="GET",              # HTTP method
            timeout=60,                # Request timeout seconds
        )

asyncio.run(main())

非同期モード(ノンブロッキング。バッチ処理やバックグラウンド処理向け):

result = await client.scrape_url(
    url="https://example.com",
    mode="async",           # Triggers, polls, returns when ready
    poll_interval=5,        # Seconds between polls
    poll_timeout=180,       # Max wait (Web Unlocker async ~2 min)
)

# Batch: pass a list of URLs
results = await client.scrape_url(
    url=["https://example.com/1", "https://example.com/2"],
    mode="async",
    poll_timeout=180,
)
# Returns List[ScrapeResult]
パターン 2:プラットフォーム固有のスクレイパー

主要なプラットフォームから構造化データを抽出します。パターン:client.scrape.<platform>.<method>(url=...)。

async with BrightDataClient() as client:
    # Amazon
    product = await client.scrape.amazon.products(url="https://amazon.com/dp/B0CRMZHDG8")
    reviews = await client.scrape.amazon.reviews(url="https://amazon.com/dp/B0CRMZHDG8")
    sellers = await client.scrape.amazon.sellers(url="https://amazon.com/dp/B0CRMZHDG8")

    # LinkedIn
    profile = await client.scrape.linkedin.profiles(url="https://linkedin.com/in/username")
    company = await client.scrape.linkedin.companies(url="https://linkedin.com/company/name")
    posts   = await client.scrape.linkedin.posts(url="https://linkedin.com/posts/...")

    # Instagram
    ig_profile  = await client.scrape.instagram.profiles(url="https://instagram.com/username")
    ig_posts    = await client.scrape.instagram.posts(url="https://instagram.com/p/...")
    ig_comments = await client.scrape.instagram.comments(url="https://instagram.com/p/...")
    ig_reels    = await client.scrape.instagram.reels(url="https://instagram.com/reel/...")

    # Facebook
    fb_posts    = await client.scrape.facebook.posts_by_profile(url="https://facebook.com/user", num_of_posts=10)
    fb_group    = await client.scrape.facebook.posts_by_group(url="https://facebook.com/groups/...", num_of_posts=10)
    fb_comments = await client.scrape.facebook.comments(url="https://facebook.com/post/...", num_of_comments=20)
    fb_reels    = await client.scrape.facebook.reels(url="https://facebook.com/reel/...")

    # YouTube
    yt_profile  = await client.scrape.youtube.profiles(url="https://youtube.com/@channel")
    yt_video    = await client.scrape.youtube.videos(url="https://youtube.com/watch?v=...")
    yt_comments = await client.scrape.youtube.comments(url="https://youtube.com/watch?v=...")

    # ChatGPT
    response = await client.scrape.chatgpt.prompt(prompt="What is Python?")
    # Batch prompts
    responses = await client.scrape.chatgpt.prompts(prompts=["Q1", "Q2", "Q3"])

    # TikTok
    tt_profile = await client.scrape.tiktok.profiles(url="https://tiktok.com/@user")

    # Reddit
    reddit_post = await client.scrape.reddit.posts(url="https://reddit.com/r/...")

すべてのスクレイパーメソッドは .success、.data、.cost、.status を持つ ScrapeResult を返します。

パターン 3:検索による発見(キーワードベース)

URL の代わりにキーワードでコンテンツを検索します。

async with BrightDataClient() as client:
    # Amazon product search
    results = await client.scrape.amazon.products_search(keyword="wireless headphones")

    # LinkedIn searches
    profiles = await client.scrape.linkedin.profiles_search(keyword="data engineer", location="San Francisco")
    jobs     = await client.scrape.linkedin.jobs_search(keyword="python developer", location="New York")
    companies = await client.scrape.linkedin.companies_search(keyword="AI startup")

    # Instagram search
    ig_profiles = await client.scrape.instagram.profiles_search(user_name="photography")
    ig_posts    = await client.scrape.instagram.posts_search(url="https://instagram.com/user", num_of_posts=20)
    ig_reels    = await client.scrape.instagram.reels_search(url="https://instagram.com/user", num_of_posts=10)

    # YouTube search
    videos = await client.scrape.youtube.videos_search(keyword="python tutorial", num_of_videos=10)
パターン 4:SERP(検索エンジンの検索結果)
async with BrightDataClient() as client:
    # Google
    result = await client.search.google(
        query="python web scraping",
        location="United States",    # Optional
        language="en",               # Default: "en"
        device="desktop",            # "desktop" or "mobile"
        num_results=10,              # Number of results
    )
    for item in result.data:
        print(item["title"], item["link"])

    # Bing
    result = await client.search.bing(query="python tutorial", num_results=10)

    # Yandex
    result = await client.search.yandex(query="python", num_results=10)

SERP の非同期モード:

result = await client.search.google(
    query="python",
    mode="async",
    poll_interval=2,
    poll_timeout=30,
)

SERP は .data(辞書のリスト)、.query、.search_engine を持つ SearchResult を返します。

パターン 5:データセット API

事前に収集された 175 種類以上の構造化データセットにアクセスします。

async with BrightDataClient() as client:
    # Filter a dataset - returns snapshot_id (string)
    snapshot_id = await client.datasets.imdb_movies(
        filter={"name": "title", "operator": "includes", "value": "black"},
        records_limit=5,
    )

    # Download results (polls until ready)
    data = await client.datasets.imdb_movies.download(snapshot_id)
    print(f"Got {len(data)} records")

    # Quick sample (no filter needed)
    snapshot_id = await client.datasets.amazon_products.sample(records_limit=10)
    data = await client.datasets.amazon_products.download(snapshot_id)

    # Get field metadata
    metadata = await client.datasets.imdb_movies.get_metadata()
    for name, field in metadata.fields.items():
        print(f"{name}: {field.type}")

ファイルにエクスポートする場合:

from brightdata.datasets import export

export(data, "results.json")    # JSON
export(data, "results.csv")     # CSV
export(data, "results.jsonl")   # JSONL

利用可能なデータセットには、次のものが含まれます: amazon_products、amazon_reviews、linkedin_profiles、linkedin_companies、linkedin_jobs、airbnb_properties、imdb_movies、google_maps_reviews、yelp_businesses、glassdoor_companies、zillow_properties、instagram_profiles、tiktok_profiles、facebook_pages_posts、reddit_posts、goodreads_books、nba_players_stats など、ほかに 150 種類以上。

パターン 6:Scraper Studio(カスタムスクレイパー)

Bright Data の Scraper Studio で構築したカスタムスクレイパーを実行します。

async with BrightDataClient() as client:
    # High-level: trigger + poll + return
    data = await client.scraper_studio.run(
        collector="c_abc123",                          # Collector ID from dashboard
        input={"url": "https://example.com/page"},     # Input for the scraper
        timeout=180,                                    # Max wait seconds
        poll_interval=10,                               # Poll frequency
    )

    # Manual control
    job = await client.scraper_studio.trigger(
        collector="c_abc123",
        input={"url": "https://example.com/page"},
    )
    print(job.response_id)
    status = await job.status()        # Returns JobStatus enum
    data = await job.wait_and_fetch(timeout=120, poll_interval=10)
パターン 7:Browser API(CDP)

Chrome DevTools Protocol 経由で Bright Data のクラウドブラウザーに接続します。

from brightdata import BrightDataClient

client = BrightDataClient(
    browser_username="brd-customer-hl_xxx-zone-scraping_browser1",
    browser_password="your_password",
)
# Or use env vars: BRIGHTDATA_BROWSERAPI_USERNAME, BRIGHTDATA_BROWSERAPI_PASSWORD

url = client.browser.get_connect_url(country="us")  # Optional country

# With Playwright
from playwright.async_api import async_playwright

async with async_playwright() as pw:
    browser = await pw.chromium.connect_over_cdp(url)
    page = await browser.new_page()
    await page.goto("https://example.com")
    content = await page.content()
    await browser.close()
パターン 8:手動でのトリガー/ポーリング/取得

時間のかかるスクレイピングを細かく制御する場合に使用します。

async with BrightDataClient() as client:
    # Step 1: Trigger (non-blocking)
    job = await client.scrape.amazon.products_trigger(url="https://amazon.com/dp/B123")
    print(f"Snapshot ID: {job.snapshot_id}")

    # Step 2: Check status
    status = await job.status()  # "ready", "running", etc.

    # Step 3: Wait for completion
    await job.wait(timeout=180, poll_interval=10, verbose=True)

    # Step 4: Fetch results
    data = await job.fetch()

    # Or combine wait + fetch into ScrapeResult:
    result = await job.to_result(timeout=180)
    print(result.data)
パターン 9:並行バッチ処理
import asyncio
from brightdata import BrightDataClient

async def main():
    async with BrightDataClient() as client:
        # Concurrent scraping
        urls = [
            "https://amazon.com/dp/B001",
            "https://amazon.com/dp/B002",
            "https://amazon.com/dp/B003",
        ]
        tasks = [client.scrape.amazon.products(url=u) for u in urls]
        results = await asyncio.gather(*tasks)

        for r in results:
            print(f"{r.url}: success={r.success}, cost=${r.cost:.4f}")

        # Concurrent SERP queries
        queries = ["python", "javascript", "rust"]
        search_tasks = [client.search.google(query=q) for q in queries]
        search_results = await asyncio.gather(*search_tasks)

asyncio.run(main())
パターン 10:同期クライアント

スクリプト、ノートブック、または非同期ではないコードベース向けです。

from brightdata import SyncBrightDataClient

with SyncBrightDataClient() as client:
    # All methods are synchronous - no await needed
    result = client.scrape_url("https://example.com")
    print(result.data)

    result = client.scrape.amazon.products(url="https://amazon.com/dp/B123")
    result = client.search.google(query="python")

    # Datasets
    snapshot_id = client.datasets.imdb_movies(
        filter={"name": "title", "operator": "includes", "value": "black"},
        records_limit=5,
    )
    data = client.datasets.imdb_movies.download(snapshot_id)

警告: async def 関数内で SyncBrightDataClient を使用しないでください。RuntimeError が発生します。

結果オブジェクトのリファレンス

すべての結果は BaseResult を継承します。

result.success          # bool - operation succeeded
result.cost             # Optional[float] - cost in USD
result.error            # Optional[str] - error message if failed
result.elapsed_ms()     # Optional[float] - total time in ms
result.to_dict()        # Dict - serializable dictionary
result.to_json(indent=2)  # str - JSON string
result.save_to_file("out.json")  # Save to file

ScrapeResult の追加フィールド:

result.url              # str - original URL
result.status           # "ready" | "error" | "timeout" | "in_progress"
result.data             # Any - scraped data (dict, list, or HTML string)
result.snapshot_id      # Optional[str] - Bright Data snapshot ID
result.platform         # Optional[str] - "amazon", "linkedin", etc.
result.row_count        # Optional[int] - number of data rows

SearchResult の追加フィールド:

result.query            # Dict - original query params
result.data             # List[Dict] - search results
result.search_engine    # "google" | "bing" | "yandex"
result.total_found      # Optional[int] - total results found

エラー処理

from brightdata import (
    BrightDataClient,
    BrightDataError,
    ValidationError,
    AuthenticationError,
    APIError,
    NetworkError,
)

async with BrightDataClient() as client:
    try:
        result = await client.scrape_url("https://example.com")
    except AuthenticationError:
        print("Invalid API token")
    except APIError as e:
        print(f"API error {e.status_code}: {e.message}")
        print(f"Response: {e.response_text}")
    except NetworkError:
        print("Network connectivity issue")
    except ValidationError:
        print("Invalid input parameters")
    except BrightDataError as e:
        print(f"Bright Data error: {e.message}")

クライアントの設定

client = BrightDataClient(
    token="...",                    # API token (or use env var)
    timeout=30,                     # Default request timeout (seconds)
    web_unlocker_zone="sdk_unlocker",  # Web Unlocker zone name
    serp_zone="sdk_serp",          # SERP zone name
    auto_create_zones=True,        # Auto-create zones if missing
    validate_token=False,          # Validate token on init
    rate_limit=10.0,               # Max requests per rate_period (None to disable)
    rate_period=1.0,               # Rate limit window (seconds)
)

ゾーンの自動作成: デフォルトでは、SDK は初回使用時に sdk_unlocker と sdk_serp ゾーンを作成します。無効にするには、auto_create_zones=False を設定してください。

ゾーン管理

async with BrightDataClient() as client:
    # List all active zones
    zones = await client.list_zones()
    for zone in zones:
        print(f"{zone['name']}: {zone.get('type', 'unknown')}")

    # Delete a zone
    await client.delete_zone("test_zone")

    # Test connection
    is_valid = await client.test_connection()

よくある間違いとその回避方法

  1. コンテキストマネージャーを忘れる:

    # WRONG - will raise RuntimeError
    client = BrightDataClient()
    result = await client.scrape_url("https://example.com")
    
    # CORRECT
    async with BrightDataClient() as client:
        result = await client.scrape_url("https://example.com")
    
  2. 非同期コードで同期クライアントを使用する:

    # WRONG - will raise RuntimeError
    async def main():
        with SyncBrightDataClient() as client:
            result = client.scrape_url("...")
    
    # CORRECT
    async def main():
        async with BrightDataClient() as client:
            result = await client.scrape_url("...")
    
  3. await を忘れる:

    # WRONG - returns coroutine, not result
    result = client.scrape_url("https://example.com")
    
    # CORRECT
    result = await client.scrape_url("https://example.com")
    
  4. result.success を確認しない:

    result = await client.scrape_url("https://example.com")
    # Always check success before using data
    if result.success:
        process(result.data)
    else:
        print(f"Failed: {result.error}")
    
  5. API トークンをハードコードする:

    # WRONG
    client = BrightDataClient(token="abc123secret")
    
    # CORRECT - use environment variable
    # export BRIGHTDATA_API_TOKEN=abc123secret
    client = BrightDataClient()
    

環境変数

変数用途デフォルト
BRIGHTDATA_API_TOKENAPI 認証トークン必須
WEB_UNLOCKER_ZONEWeb Unlocker ゾーン名sdk_unlocker
SERP_ZONESERP ゾーン名sdk_serp
BRIGHTDATA_BROWSERAPI_USERNAMEBrowser API ユーザー名なし
BRIGHTDATA_BROWSERAPI_PASSWORDBrowser API パスワードなし

すぐにわかる方法選び

タスク方法
任意の URL(HTML)をスクレイピングするclient.scrape_url(url)
Amazon/LinkedIn などをスクレイピングする(構造化データ)client.scrape.<platform>.<method>(url=...)
Google/Bing/Yandex を検索するclient.search.google(query=...)
キーワードで商品/プロフィールを検索するclient.scrape.<platform>.<type>_search(keyword=...)
収集済みのデータセットにアクセスするclient.datasets.<name>(filter=..., records_limit=...)
カスタムの Scraper Studio スクレイパーを実行するclient.scraper_studio.run(collector=..., input=...)
ブラウザーを自動化する(Playwright/Puppeteer)client.browser.get_connect_url()
手動制御で長時間実行するスクレイピングclient.scrape.<platform>.<method>_trigger(url=...) を実行し、その後 job.wait() + job.fetch()

API の全機能と高度な使用パターンについては、references/api-reference.md をご覧ください。

コメント