无需 KYC — 无需 ID、无需自拍、无需文件。使用加密货币支付:BTC, USDT, USDC, ETH, SOL, LTC
语言: 简体中文
获取 API 密钥

文档 · Python 3.9+ · requests · httpx

Python 中的 SERP API:requests、httpx 和 asyncio

一个可复用的客户端,带重试、在结果结束时就停止的分页循环、受并发限制的异步搜索,以及用于排名的每日 CSV。可直接复制的代码,已做语法检查,无需安装我们的任何包。

最后更新: · 3 分钟阅读

快速回答

如何从 Python 调用 SERP API?

向 https://serpcrypto.com/api/v1/search 发送 GET 请求,带上 requests 或 httpx,将密钥放在 Authorization: Bearer 请求头中,将查询放在 params 中,然后读取 response.json()。SerpCrypto 每次成功搜索收取 1 个积分,从 US$0.30/千次搜索 起,失败调用的重试免费。使用加密货币支付,无需 KYC。下面的代码只需要 requests 或 httpx。

Python 设置一览

安装pip install requests 或 pip install httpx
密钥环境变量 SERPCRYPTO_API_KEY
请求头Authorization: Bearer <key>
超时60 到 90 秒:搜索实时运行
重试仅 429、502 和 504,带退避;错误免费
并行查询最高 concurrency_limit,从 GET /credits 起

如何设置可复用的 Python 客户端?

创建一个 requests.Session,将密钥放在其请求头中,并为三种临时错误设置重试策略。会话会复用连接,因此搜索循环在 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 条结果?

逐页请求下一页。每页约 10 条自然结果,这是 Google 自 2025 年 9 月起不再支持 num=100 后的返回方式;每多一页就多消耗 1 积分。一旦 pagination.next_page 缺失就停止:没有更多可抓取的内容,这样还能节省积分。

对于大多数排名跟踪工作,第一页或前三页就足够了,因为点击集中在那里。一个关键词的三十条结果花费三个积分。

分页:最多三页,提前停止
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;信号量可以避免浪费这些尝试。

每个任务都会以递增的暂停重试临时错误,并在四次失败后返回 None,因此一个顽固的查询永远不会阻塞整个批次。

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 文件?

为每条结果追加一行,包含日期、关键词、位置、链接以及 API 应用了的设置。从 search_parameters 读取 gl 和 device 而不是从你自己的变量读取,意味着文件记录的是实际使用的内容。

使用 cron 或 Windows 任务计划程序每天运行一次脚本。移动端三个关键词每天花费三个积分,每月约 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:它简单,重试适配器也成熟。需要异步代码时用 httpx,比如 web 应用、agent 或成百上千个关键词的批量任务。两者发出同样的请求、拿到同样的 JSON;API 不在乎你选哪个。

用哪个库都别把超时设得太短。五秒就放弃的客户端可能会重发一个还在运行的查询,然后两份都付钱。

我的脚本要花多少钱?

按查询次数算,不按结果数算:一次调用成功就是 1 个积分。500 个关键词、每个一页,每天跑一次,连续 30 天,就是 15,000 次查询。用 25,000 次搜索 积分包(US$18.75)绰绰有余,预付的搜索积分永不过期:未使用的查询会一直留在你的账户中,直到你使用它们。

在代码里用上面的 credits() 辅助函数查余额;不花积分。

Python 相关问题

PyPI 上有 SerpCrypto 包吗?

没有。示例用 requests 或 httpx(两个广泛使用的库)调用 HTTPS endpoint,所以我们这边没有东西需要安装或更新。上面的 client 大约 40 行,由你自己掌控。

这段代码支持哪些 Python 版本?

Python 3.9 及以上。异步示例用了 asyncio.run,从 Python 3.7 起可用;其余部分只用标准库加上 requests 或 httpx。

我能在 Jupyter notebook 里用这个 API 吗?

可以。启动 Jupyter 前设置 SERPCRYPTO_API_KEY,或者在 notebook 里用 getpass 读取 API 密钥,这样它就不会留在保存的 cell 里。在 notebook 中,用 await main(...) 而不是 asyncio.run(main(...))。

怎么把结果转成 pandas DataFrame?

把结果字典的列表传给 pandas.DataFrame(data["organic_results"])。每个字段变成一列;缺失的可选字段(比如 date)会变成空单元格。

起价 US$0.30/千次搜索 · 无需 KYC

获取 API 密钥