Python 网页抓取教程:使用 TalorData SERP API 采集结构化搜索数据
手把手 Python 教程:安装 TalorData SDK、发送 SERP 请求、解析结构化结果、处理分页、导出 JSON/CSV,并安全测试集成。
了解手动解析搜索 HTML 与使用官方 TalorData Python SDK 采集结构化搜索数据的实际差异。
网页抓取是从页面或在线服务中采集信息的技术。Python 因其可读性、庞大的生态系统以及与数据、AI 和自动化工具的无缝集成,成为这项工作的热门选择。
然而,当目标是搜索引擎结果页时,下载 HTML 并猜测 CSS 选择器的方式往往非常脆弱。搜索引擎会呈现不同的布局、要求 JavaScript 执行、应用本地化设置,并且在不通知的情况下更改标记结构。TalorData 提供的 SERP API 通过一次经过身份验证的请求即可返回结构化搜索数据,让你的 Python 代码直接处理数据字段,而非页面标记。
本教程你将学到:对比手动 HTML 抓取与 SERP API 的区别,安装 talordata-serp,发送搜索请求,读取结构化结果,处理 JSON 和 HTML 响应模式,对大结果集进行分页,将数据导出为 JSON 和 CSV,以及在不消耗真实 API 请求的情况下安全测试集成。
使用 Python 采集搜索数据的工具
搜索数据采集有两种主要方式:自行抓取页面并解析 HTML,或使用在服务端完成采集和标准化的搜索 API。
| 方式 | 常用 Python 工具 | 适用场景 | 权衡 |
|---|---|---|---|
| 手动 HTML 抓取 | requests、httpx、HTML 解析器 | 你控制的站点或稳定的公开页面 | 你需要自行维护选择器、处理渲染差异、速率限制和响应解析。 |
| 浏览器自动化 | Playwright、Selenium、浏览器驱动 | 测试或需要可见浏览器交互的工作流 | 运行时和基础设施开销更大;对于结构化 SERP 响应并非必要。 |
| TalorData SERP API | talordata-serp | 搜索、RAG、SEO、研究和数据管道 | 需要 API 令牌和账户额度;API 处理搜索页面采集层。 |
本教程聚焦于第三种方式。SDK 使用 Python 标准数据结构,因此你可以将其结果直接传递给数据库、DataFrame 库、LLM 工作流或 CSV 写入器。
手动 HTML 抓取 vs SERP API
使用手动抓取时,应用通常遵循以下流程:
- 构建 URL 并发送 HTTP 请求。
- 处理状态码、请求头、JavaScript 渲染和速率限制。
- 使用 CSS 选择器解析 HTML 并定位结果块。
- 将字段标准化为应用特定的 Schema。
- 当搜索引擎更改标记时,重复以上维护工作。
使用 TalorData 时,你的应用只需向 /serp/v1/request 发送搜索参数。SDK 自动添加 Bearer 身份验证、发送表单编码数据、解析响应并返回类似字典的结果对象。你专注于数据的使用方式,而非数据的获取过程。
import os
from talordata_serp import Client
client = Client(api_token=os.getenv("TALORDATA_API_TOKEN"))
results = client.search(engine="google", q="python data pipelines")
分步指南:基础 TalorData 工作流
以下示例使用 Talordata/talordata-serp-python 仓库中的公开接口。
前提条件
- Python 3.8 或更新版本。
- TalorData 账户和 API 令牌。
- 基本的 Python 和字典操作知识。
- 用于项目依赖的虚拟环境。
步骤 1:安装 SDK
python -m pip install talordata-serp
该包依赖 requests,并从 talordata_serp 模块导出客户端和异常类。
步骤 2:配置 API 令牌
将凭据保存在源代码文件之外。在运行脚本前设置环境变量:
# macOS / Linux
export TALORDATA_API_TOKEN="paste-your-token-here"
# PowerShell
$env:TALORDATA_API_TOKEN = "paste-your-token-here"
Client 也接受显式的 api_token 参数,适用于密钥管理器在运行时注入值的场景。
步骤 3:发送首次搜索
import os
from talordata_serp import Client
client = Client(api_token=os.getenv("TALORDATA_API_TOKEN"))
result = client.search(
engine="google",
q="python web scraping",
)
print("status:", result.status)
print("metadata:", result.search_metadata)
client.search() 默认使用 json=1。当响应包含 JSON 对象时,SDK 将其包装在 SerpResults 中,行为与普通 Python 字典一致。
步骤 4:添加请求参数
通过关键字参数或映射传递参数。设为 None 的值会被自动省略。Python 布尔值会被标准化为 "1" 和 "0" 用于表单请求。
params = {
"engine": "google",
"q": "python RAG tutorial",
"location": "Austin, Texas",
"safe": True,
}
result = client.search(params)
print(result.as_dict())
读取结构化结果
使用字典访问引擎特定的结果块,使用辅助属性读取通用元数据:
print(result.status)
print(result.search_metadata)
search_info = result.get("search_information", {})
print(search_info.get("query_displayed"))
# 将包装器转换为普通字典,供其他库使用。
payload = result.as_dict()
结果块是可选的。当某个字段可能不会在特定引擎或查询类型中返回时,优先使用 get() 或设置默认值。
静态 HTML 与动态搜索页面
传统的 Python 抓取教程通常将页面分为静态 HTML 和 JavaScript 密集型内容。静态页面有时可以用 requests 获取,而动态页面可能需要浏览器会话和显式的等待逻辑。
SERP API 改变了这一权衡。你的应用始终保持在结构化 API 边界,无需检查搜索页面的 DOM 来提取标题、链接、摘要或元数据。
# 应用直接消费结构化数据,而非 CSS 选择器。
organic_results = result.get("organic_results", [])
for item in organic_results:
print(item.get("title"), item.get("link"))
这并不意味着所有网站都能自动被抓取,也不意味着 API 可以替代所有浏览器自动化。而是说,当你的目标是搜索结果数据而非与私有 Web 应用的任意交互时,TalorData 是正确的抽象层。
选择响应模式
SDK 为 TalorData 端点支持的每种输出格式提供了辅助方法。
结构化 JSON
result = client.search(engine="google", q="pizza")
plain = client.search_json(engine="google", q="pizza")
print(result.status)
print(plain["search_metadata"])
JSON + HTML 组合
模式 json=2 返回 HTML 和一个嵌套的 JSON 字符串。SDK 会在嵌套 JSON 有效时自动尝试解码。
combined = client.search(engine="google", q="pizza", json=2)
print(combined.get("html"))
print(combined.get("json", {}).get("search_metadata"))
HTML 或原始响应文本
html = client.search_html(
engine="google",
q="pizza",
)
print(html[:500])
raw_body = client.raw_search(engine="google", q="pizza")
print(raw_body[:500])
当你明确需要标记内容时使用 HTML 模式。对于应用逻辑,请尽可能使用默认的 JSON 模式——速度更快,且避免了脆弱的 DOM 解析。
分页与批量搜索
分页由所选引擎支持的参数控制。对于 Google 风格的查询,通常使用 start 偏移量:
for start in (0, 10, 20):
page = client.search(
engine="google",
q="python web scraping",
start=start,
)
print(start, page.status)
对于小批量任务,普通循环清晰且易于监控:
queries = ["Python RAG", "Python SEO", "Python search API"]
for query in queries:
page = client.search(engine="google", q=query)
print(query, page.search_metadata.get("status"))
对于更大规模的工作负载,请添加有界并发、日志记录和符合账户额度的应用级速率限制。SDK 不会静默重试请求或提供内置分页器——这使得集成行为显式且可预测。
导出搜索数据
由于 as_dict() 返回普通 Python 数据,标准库导出器无需任何 TalorData 专用适配器即可工作。
导出为 JSON
import json
with open("search-result.json", "w", encoding="utf-8") as file:
json.dump(result.as_dict(), file, ensure_ascii=False, indent=2)
导出指定字段为 CSV
import csv
organic = result.get("organic_results", [])
with open("organic-results.csv", "w", newline="", encoding="utf-8") as file:
writer = csv.DictWriter(file, fieldnames=["title", "link", "snippet"])
writer.writeheader()
for item in organic:
writer.writerow({
"title": item.get("title", ""),
"link": item.get("link", ""),
"snippet": item.get("snippet", ""),
})
生产环境错误处理
该包导出了针对缺少凭据和常见传输故障的命名异常。在应用边界捕获它们,以便你的 Worker、CLI 工具或 Web 服务可以报告有用的错误状态。
from talordata_serp import (
APITokenNotProvided,
HTTPConnectionError,
HTTPError,
TimeoutError,
)
try:
result = client.search(engine="google", q="pizza")
except APITokenNotProvided:
print("运行任务前请设置 TALORDATA_API_TOKEN。")
except TimeoutError:
print("请求超时。")
except HTTPConnectionError:
print("无法连接 TalorData。")
except HTTPError as error:
print("HTTP 状态码:", error.status_code)
print("API 错误:", error.error)
设置客户端级别的超时或为单个请求覆盖超时:
client = Client(
api_token=os.getenv("TALORDATA_API_TOKEN"),
timeout=15,
)
result = client.search(engine="google", q="pizza", timeout=10)
无需真实请求即可测试集成
SDK 接受自定义 requests.Session。这允许你使用伪造的 Session 来断言请求方法、URL、请求头和表单载荷——无需暴露凭据,也不消耗真实的 API 请求。
from talordata_serp import Client
class FakeSession:
def request(self, **kwargs):
assert kwargs["method"] == "POST"
assert kwargs["url"].endswith("/serp/v1/request")
assert kwargs["data"]["json"] == "1"
raise AssertionError("在真实测试中返回一个 fixture 响应")
client = Client(api_token="test-token", session=FakeSession())
仓库中还包含可运行的示例:examples/ 目录下的 basic_search.py 和 html_output.py。
复用客户端处理任务
使用一个客户端处理相关请求,并通过上下文管理器确定性地关闭其 Session:
import os
from talordata_serp import Client
with Client(api_token=os.getenv("TALORDATA_API_TOKEN")) as client:
first = client.search(engine="google", q="Python")
second = client.search(engine="google", q="TalorData")
print(first.status, second.status)
为什么选择 Python + TalorData?
- 可读的集成代码:搜索请求就是一个普通的 Python 函数调用。
- 强大的数据生态:JSON 结果可直接传递给 CSV 写入器、数据库、DataFrame 和 AI 管道。
- 可复用的工作流:一个客户端即可驱动搜索 Copilot、RAG 检索、SEO 监控、研究任务和定时自动化。
- 清晰的故障处理:令牌、超时、连接和 HTTP 错误均以命名异常暴露。
- 更少的页面维护:你的应用消费响应字段,而非将业务逻辑耦合到搜索页面的 CSS 选择器。
TalorData 不是通用的浏览器自动化框架。它是一个专注的搜索数据 API。这一边界使其成为你需要结构化 SERP 数据时的正确选择。
常见问题
使用 SERP API 和直接抓取网站是一回事吗?
它们是不同的集成层。手动抓取在你的应用中下载并解析页面。SERP API 通过经身份验证的 API 响应暴露搜索数据。你的应用仍应遵循 API 条款、账户额度和适用法律。
本教程需要 Beautiful Soup 或 Selenium 吗?
不需要。那些工具适用于其他类型的 Web 自动化,但本教程使用 TalorData SDK 直接获取搜索结果,不会在你的进程中解析搜索页面的 DOM。
API 令牌应该保存在哪里?
本地使用 TALORDATA_API_TOKEN 环境变量,生产环境使用部署密钥管理器。切勿将真实令牌提交到代码仓库或放置在浏览器端 JavaScript 中。
应该选择哪种输出模式?
结构化应用数据使用默认的 JSON 模式。需要显式普通字典时使用 search_json(),需要 HTML 输出时使用 search_html(),需要未处理的响应体时使用 raw_search()。
完整示例在哪里?
参见 TalorData Python SDK GitHub 仓库获取 README、包源码、测试和可运行示例。使用 官方 SERP API 文档查看引擎特定参数。
以上就是完整的工作流:安装 SDK、保护令牌、发送结构化搜索请求、仅导出应用需要的字段,并将 API 边界与业务逻辑分离。接下来,你可以探索 引擎特定参数或浏览 SDK GitHub 源码。