快速回答
如何从 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: 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,因此一个顽固的查询永远不会阻塞整个批次。
"""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 个。
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)会变成空单元格。