KYC不要 — 身分証、自撮り、書類は不要です。暗号資産で支払い: BTC, USDT, USDC, ETH, SOL, LTC
言語: 日本語
APIキーを取得

Docs · Python 3.9+ · requests · httpx

PythonでのSERP API: requests、httpx、asyncio

リトライ付きの再利用可能なクライアント、結果が終わったら停止するページネーションループ、同時実行数の上限内に制限したasync検索、ランキング用の日次CSV。コピー&ペースト可能なコードで、構文チェック済み、当社のパッケージをインストールする必要はありません。

最終更新:

簡潔な回答

PythonからSERP APIを呼び出すには?

https://serpcrypto.com/api/v1/searchにGETリクエストを送信し、requestsまたはhttpxを使い、Authorization: Bearerヘッダーにキー、paramsに検索クエリを設定して、response.json()を読み取ります。SerpCryptoは成功した検索1回につき1クレジットを$0.30/1K検索から課金し、失敗した呼び出しのリトライは無料です。暗号資産で支払い、KYC不要。以下のコードはrequestsまたはhttpxのみ必要です。

Pythonのセットアップ概要

インストールpip install requestsまたはpip install httpx
キー環境変数SERPCRYPTO_API_KEY
ヘッダーAuthorization: Bearer <key>
タイムアウト60〜90秒: 検索はライブで実行されます
リトライ429、502、504のみ、バックオフ付き。エラーは無料
並列検索GET /creditsから最大concurrency_limit

再利用可能なPythonクライアントをセットアップするには?

ヘッダーにキーを設定し、3つの一時的エラーに対するリトライポリシーを持つrequests.Sessionを1つ作成します。セッションは接続を再利用するので、検索のループでTLSハンドシェイクに費やす時間が減ります。ファイルをserp_client.pyとして保存してください。次の例ではこれをインポートします。

urllib3のRetryは、各試行前に長く待機し、Retry-Afterヘッダーが送信された場合はそれに従います。400、401、402はリトライしません。これらは再試行ではなく修正が必要です。

serp_client.py
"""serp_client.py: a small, reusable client for the SerpCrypto SERP API (requests)."""
import os

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

API_URL = "https://serpcrypto.com/api/v1/search"
CREDITS_URL = "https://serpcrypto.com/api/v1/credits"


def make_session():
    session = requests.Session()
    session.headers["Authorization"] = "Bearer " + os.environ["SERPCRYPTO_API_KEY"]
    retry = Retry(
        total=4,
        backoff_factor=1.0,  # waits about 1 s, 2 s, 4 s between attempts
        status_forcelist=(429, 502, 504),
        allowed_methods=("GET",),
        respect_retry_after_header=True,
    )
    session.mount("https://", HTTPAdapter(max_retries=retry))
    return session


SESSION = make_session()


def search(q, **params):
    """Run one search (1 credit if it succeeds) and return the parsed JSON."""
    r = SESSION.get(API_URL, params={"q": q, **params}, timeout=90)
    r.raise_for_status()
    return r.json()


def credits():
    """Free: credits left, used today and the concurrency limit."""
    r = SESSION.get(CREDITS_URL, timeout=30)
    r.raise_for_status()
    return r.json()


if __name__ == "__main__":
    data = search("project management software", gl="us", hl="en")
    for item in data.get("organic_results", []):
        print(item["position"], item["link"])
    print(credits())

10件を超える結果を取得するには?

次のページを1つずつ要求します。1ページあたり約10件のオーガニック結果です。Googleは2025年9月にnum=100を尊重しなくなって以降、この件数を返しています。追加の各ページにはさらに1クレジットが必要です。pagination.next_pageが欠落したらすぐに停止します。これ以上取得するものはなく、クレジットを節約できます。

ほとんどのランキング追跡作業では、1ページ目または最初の3ページで十分です。クリックがそこに集中するためです。1つのキーワードで30件の結果は3クレジットかかります。

ページネーション: 最大3ページ、早期停止
from serp_client import search


def top_results(q, pages=3, **params):
    """Collect organic results over several pages: each page is 1 credit."""
    rows = []
    for page in range(1, pages + 1):
        data = search(q, page=page, **params)
        for item in data.get("organic_results", []):
            rows.append({"page": page, "position": item["position"], "title": item["title"], "link": item["link"]})
        if not data.get("pagination", {}).get("next_page"):
            break  # no further page: stop early and save credits
    return rows


rows = top_results("crm for small business", pages=3, gl="gb", hl="en")
print(len(rows), "results")

多数の検索を並列で実行するには?

httpx.AsyncClientをasyncio.Semaphoreとともに使用し、アカウントの制限に合わせてサイズを設定します。スクリプトは無料クレジットのエンドポイントからconcurrency_limitを読み取るので、サポートが制限を引き上げるとそれに適応します。制限を超える検索はどのみち429になるため、セマフォでそれらの試行を無駄にしません。

各タスクは一時的エラーを徐々に長くなる間隔でリトライし、4回失敗するとNoneを返すので、1つの厄介なクエリがバッチをブロックすることはありません。

asyncio + httpx: 制限内での並列検索
"""Run many searches in parallel without exceeding the account's concurrency limit."""
import asyncio
import os

import httpx

API_URL = "https://serpcrypto.com/api/v1/search"
CREDITS_URL = "https://serpcrypto.com/api/v1/credits"
HEADERS = {"Authorization": "Bearer " + os.environ["SERPCRYPTO_API_KEY"]}


async def search_one(client, gate, q):
    async with gate:  # at most N searches at the same time
        for attempt in range(4):
            r = await client.get(API_URL, params={"q": q, "gl": "us", "hl": "en"})
            if r.status_code in (429, 502, 504):
                await asyncio.sleep(2 ** attempt)
                continue
            r.raise_for_status()
            return q, r.json()
        return q, None


async def main(queries):
    async with httpx.AsyncClient(headers=HEADERS, timeout=90) as client:
        limits = (await client.get(CREDITS_URL)).json()
        gate = asyncio.Semaphore(limits["concurrency_limit"])
        results = await asyncio.gather(*(search_one(client, gate, q) for q in queries))
    for q, data in results:
        first = (data or {}).get("organic_results", [{}])[0].get("link")
        print(f"{q!r}: {first}")


asyncio.run(main(["best vpn router", "home espresso machine", "4k monitor for coding"]))

日次ランキングをCSVファイルに保存するには?

結果ごとに1行を追加し、日付、キーワード、順位、リンク、APIが適用した設定を記録します。独自の変数ではなくsearch_parametersからglとdeviceを読み取ることで、ファイルには実際に使用された内容が記録されます。

cronまたはWindowsタスクスケジューラで1日1回スクリプトを実行します。モバイルで3つのキーワードは1日3クレジット、月約90クレジットです。

本日のランキングをrankings.csvに追加
import csv
from datetime import date

from serp_client import search

KEYWORDS = ["standing desk", "ergonomic chair", "monitor arm"]
FIELDS = ["day", "keyword", "position", "title", "link", "gl", "device"]

with open("rankings.csv", "a", newline="", encoding="utf-8") as fh:
    writer = csv.DictWriter(fh, fieldnames=FIELDS)
    if fh.tell() == 0:
        writer.writeheader()
    for kw in KEYWORDS:
        data = search(kw, gl="gb", hl="en", device="mobile")
        applied = data["search_parameters"]
        for item in data.get("organic_results", []):
            writer.writerow({
                "day": date.today().isoformat(),
                "keyword": kw,
                "position": item["position"],
                "title": item["title"],
                "link": item["link"],
                "gl": applied["gl"],
                "device": applied["device"],
            })

どのPython HTTPクライアントを使うべきですか?

スクリプトやcronジョブにはrequestsを使いましょう。シンプルで、リトライアダプターが成熟しています。非同期コードが必要な場合、たとえばWebアプリ、エージェント、数百キーワードのバッチ処理にはhttpxを使いましょう。どちらも同じリクエストを送り、同じJSONを受け取ります。APIはどちらを選んでも関係ありません。

どちらのライブラリでも、極端に短いタイムアウトは避けてください。5秒で諦めるクライアントは、まだ実行中だった検索を再送してしまい、二重に支払う可能性があります。

スクリプトのコストはいくらになりますか?

結果ではなく検索回数を数えます。成功した1回の呼び出しが1クレジットです。500キーワードを1ページずつ、毎日30日間実行するジョブは15,000回の検索になります。25,000検索パック($18.75)なら余裕があり、プリペイドの検索クレジットに有効期限はありません。未使用の検索は、使用するまでアカウントに残ります。

コードからは上のcredits()ヘルパーで残高を確認できます。これは無料です。

Pythonに関する質問

PyPIにSerpCryptoのパッケージはありますか?

いいえ。サンプルは広く使われている2つのライブラリ、requestsまたはhttpxでHTTPS endpointを呼び出すので、インストールや更新が必要なものはありません。上のクライアントは約40行で、あなた自身が管理できます。

このコードはどのPythonバージョンに対応していますか?

Python 3.9以降です。asyncのサンプルはPython 3.7から利用可能なasyncio.runを使い、それ以外は標準ライブラリとrequestsまたはhttpxのみを使います。

Jupyter notebookからAPIを使えますか?

はい。Jupyterを起動する前にSERPCRYPTO_API_KEYを設定するか、notebook内でgetpassを使ってキーを読み込めば、保存されたセルに残りません。notebook内ではasyncio.run(main(...))の代わりにawait main(...)を使ってください。

結果をpandas DataFrameに変換するには?

結果の辞書のリストをpandas.DataFrame(data["organic_results"])に渡します。各フィールドが列になり、dateのような省略可能なフィールドが欠けている場合は空のセルになります。

$0.30/1K検索から · KYC不要

APIキーを取得