如何在Python中构建人工智能代理
Senior Web Scraping Engineer
TL;DR:
- AI代理是一个循环:模型选择工具,您的代码运行它,结果返回模型。 智力在于语言模型;能力来自您提供的工具。对于研究和监控,两个重要的工具是网页搜索和页面获取。
- 给代理真实的网络工具,而不是冻结的训练集。 使用Deep SerpApi支持的
web_search工具返回实时谷歌结果,使用Universal Scraping API支持的fetch_page工具返回渲染的HTML — 代理基于当前数据进行推理,而不是去年的数据。 - 两个工具都是一个HTTP POST请求。 搜索调用
POST /api/v1/scraper/request,使用scraper.google.search操作;获取调用POST /api/v1/unlocker/request,并开启js_render。无需管理浏览器,无需轮换代理池。 - 模型控制流程。 您暴露工具签名,模型决定何时调用,您执行并反馈结果,直到它得到答案 — 这个循环构成了整个代理。
- 保持工具层的确定性和经过验证。 搜索和获取调用返回结构化数据,您可以独立于模型进行测试,这就是可靠性来源。
- 免费开始。 新注册的Scrapeless账户包括免费Deep SerpApi运行时 — 请在app.scrapeless.com注册。
引言:一个代理的好坏取决于其工具
单独的语言模型可以推理,但它无法浏览今天的网络 — 它只能利用截止日期之前的训练数据进行回答。AI代理通过将模型封装在一个循环中来弥补这一差距:模型请求运行一个工具,您的代码对实时数据进行运行,结果返回到会话中。重复这个过程,直到模型拥有所需的信息来回答。
困难的部分往往不是循环 — 而是工具。研究代理需要搜索开放网络并读取其找到的页面,而这两者在真实网站上都会出现问题:搜索引擎限速,目标页面使用JavaScript渲染或被机器人防护所保护。手动实现这一点是大部分工作。
本指南在Python中构建一个研究代理,两个工具都是通过HTTP调用管理的:web_search运行在Scrapeless Deep SerpApi上,fetch_page运行在Universal Scraping API上。下面的工具层经过实时API验证;模型推理循环显示了标准的工具调用模式。仅使用公共数据。
管道一瞥
代理有四个部分,只有中间两个涉及网络:
- 目标输入 — 用户的问题或研究任务。
web_search(query)— 通过Deep SerpApi获得实时谷歌结果(标题、链接、摘要)。fetch_page(url)— 获取模型希望读取的任何结果的渲染HTML,通过Universal Scraping API。- 模型循环 — 语言模型决定调用哪个工具,读取结果,然后调用另一个工具或写出最终答案。
步骤2和3是< a href="https://datatracker.ietf.org/doc/html/rfc9110" rel="nofollow">确定性的HTTP调用,您可以独立验证。步骤4是模型;步骤1–3构成了其答案的时效性。
前提条件
- Python 3.10或更新版本
pip install requests(加上您的模型提供者的SDK)- 一个Scrapeless账户和API密钥 — 请在app.scrapeless.com注册
- 用于推理循环的模型提供者API密钥(步骤3)
bash
export SCRAPELESS_API_KEY="your_api_token_here"
第1步 — 网络搜索工具
搜索工具将查询发送到Deep SerpApi Google Search操作,并返回一个紧凑的自然搜索结果列表 — 标题、链接和摘要 — 这正是模型决定下一步要读取内容所需要的:
python
import os
import requests
API = "https://api.scrapeless.com"
HEADERS = {
"Content-Type": "application/json",
"x-api-token": os.environ["SCRAPELESS_API_KEY"],
}
def web_search(query: str, count: int = 5):
r = requests.post(
f"{API}/api/v1/scraper/request",
headers=HEADERS,
json={
"actor": "scraper.google.search",
"input": {"q": query, "hl": "en", "gl": "us"},
},
timeout=90,
)
r.raise_for_status()
results = r.json().get("organic_results", [])[:count]
return [
{"title": x.get("title"), "link": x.get("link"), "snippet": x.get("snippet")}
for x in results
]
# 单独运行以确认格式:
hits = web_search("best web scraping tools 2026", 3)
print(len(hits), "results")
for h in hits:
print("-", h["title"], "|", h["link"])
该操作返回包含标准搜索字段的organic_results;函数将其修剪到前count结果,以免洪泛模型的上下文数据。
在免费计划中获取您的API密钥:app.scrapeless.com
第2步 — 页面获取工具
一旦模型选择了一个结果进行阅读,它需要页面内容。提取工具将 URL 以 js_render 打开形式发送到通用抓取 API,因此客户端渲染的页面会返回已完成的 HTML,而不是一个空壳:
python
import os
import requests
API = "https://api.scrapeless.com"
HEADERS = {
"Content-Type": "application/json",
"x-api-token": os.environ["SCRAPELESS_API_KEY"],
}
def fetch_page(url: str):
r = requests.post(
f"{API}/api/v1/unlocker/request",
headers=HEADERS,
json={
"actor": "unlocker.webunlocker",
"input": {"url": url, "method": "GET", "js_render": True},
},
timeout=120,
)
r.raise_for_status()
return r.json().get("data", "")
# 获取已渲染的页面并确认我们得到了 HTML:
html = fetch_page("https://www.scrapeless.com/en")
print("获取到", len(html), "字节")
在将 HTML 提交给模型之前,使用 selectolax 或 BeautifulSoup 将其提取为文本,以便您在内容上花费上下文,而不是标记。保持工具本身返回原始 HTML —— 让代理决定阅读多少内容。
第 3 步 — 模型循环
在验证了这两个工具之后,代理是一个循环,可以让模型调用它们。将这两个工具的签名暴露给您的模型提供者的工具调用 API,然后运行标准周期:发送对话,当模型返回工具调用时,执行它并附加结果;当它返回文本时,那就是答案。
注意:这一步调用您的模型提供者,并需要该提供者的 API 密钥。上面的工具函数可以独立运行;下面的循环则是标准的工具调用模式,将其连接到它们。
python
TOOLS = [
{
"name": "web_search",
"description": "在 Google 中搜索查询;返回标题、链接、摘要。",
"input_schema": {
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"],
},
},
{
"name": "fetch_page",
"description": "获取 URL 的已渲染 HTML。",
"input_schema": {
"type": "object",
"properties": {"url": {"type": "string"}},
"required": ["url"],
},
},
]
DISPATCH = {"web_search": web_search, "fetch_page": fetch_page}
def run_agent(client, goal: str):
messages = [{"role": "user", "content": goal}]
while True:
reply = client.run(messages=messages, tools=TOOLS) # 提供者工具调用
if reply.tool_call:
name, args = reply.tool_call.name, reply.tool_call.args
result = DISPATCH[name](**args)
messages.append({"role": "tool", "name": name, "content": result})
continue
return reply.text
这个结构是提供者无关的:每个主要的工具调用 API 都会告诉您“模型想要用参数 Y 调用工具 X”,您运行 DISPATCH[X](**Y),附加结果,然后继续循环。代理的能力来自于两个工具返回真实、当前的数据——这是本指南验证的部分。
您得到的反馈
每个 web_search 结果都是一个简单的记录,模型可以直接推理:
json
[
{
"title": "2026年最佳网络抓取工具",
"link": "https://dev.to/nitinfab/best-web-scraping-tools-in-2026-i-tested-30-tools-and-these-are-the-only-ones-worth-using-11l3",
"snippet": "对抓取工具在渲染、代理和价格方面的实际比较 ..."
}
]
// 模式完全反映了 web_search 返回的内容。字段值是示例性样本。
几点诚实的观察:
- 在模型接收之前修剪搜索结果。 通常前三到五个就足够了;完整的 SERP 会浪费上下文和资金。
- 在代理中将 HTML 转换为文本,而不是在工具中。 让
fetch_page返回原始 HTML,以保持确定性;在您控制令牌预算的地方进行清理。 - 限制循环次数。 给代理一个最大工具调用次数,以防止混乱的运行无法结束——设置硬性上限,而不仅仅是重试。
- 这些工具是可以独立测试的。 由于搜索和提取是普通 HTTP,您可以在不需要模型的情况下单元测试它们,这正是可靠性的体现。
结论:工具造就了代理
研究代理是围绕一个强大模型的小循环——杠杆在于工具。使用 Deep SerpApi 支持 web_search 和使用 Universal Scraping API 支持 fetch_page,代理在实时的 Google 结果和渲染页面上进行推理,而不是依赖过时的训练数据,而且无需维护浏览器集群或代理轮换。首先构建工具,单独验证它们,然后将模型循环包裹在它们周围。对于驱动完整浏览器而不是 HTTP 调用的代理,请参见 在 Scraping Browser 上构建搜索代理;Deep SerpApi 产品页面 和 文档 涵盖了每个参与者。验证工具,让模型驱动,并限制循环。
准备好构建您的 AI 驱动数据管道了吗?
加入我们的社区,申请免费计划并与构建代理和研究管道的开发者连接:Discord · Telegram。
在 app.scrapeless.com 注册,获取免费的 Deep SerpApi 运行时,并将搜索和获取工具连接到您已经使用的代理框架中。查看 定价 以了解规模。
常见问题解答
问:构建此项需要特定的模型提供者吗?
不需要。循环是提供者无关的——任何工具调用的 API 都可以使用。将 client.run(...) 调用替换为您提供者的调用;web_search 和 fetch_page 工具保持不变。
问:为什么要使用管理的 API 而不是 requests 和无头浏览器?
因为开放网络对抗原始抓取工具:搜索引擎限制速率,并且目标页面在客户端渲染或受到挑战的限制。Deep SerpApi 和 Universal Scraping API 处理渲染和访问,因此工具返回干净的数据而不是阻塞。
问:代理的网络访问合法吗?
代理收集公开可用的数据。您存储和使用数据的方式受每个网站的服务条款和当地法律的管控——仅访问公开数据,尊重服务条款,并就您的使用案例咨询法律顾问。
问:如何防止代理无限循环?
限制每次运行的工具调用次数,当达到上限时停止。这是控制流的硬性上限,而不是错误处理。
问:获取的页面可以有多大?
大型——单个内容页面可以返回数百千字节的 HTML。在传递给模型之前转换为文本并截断,以便控制上下文预算。
问:代理可以使用两个以上的工具吗?
可以。将任何返回结构化数据的工具添加到 TOOLS 列表和 DISPATCH 映射中,模型可以以相同的方式调用它。
在Scrapeless,我们仅访问公开可用的数据,并严格遵循适用的法律、法规和网站隐私政策。本博客中的内容仅供演示之用,不涉及任何非法或侵权活动。我们对使用本博客或第三方链接中的信息不做任何保证,并免除所有责任。在进行任何抓取活动之前,请咨询您的法律顾问,并审查目标网站的服务条款或获取必要的许可。



