news 2026/10/6 2:46:27

【三个月 AI Agent 实战学习】Day 28:项目 —— 网络爬虫 Agent

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【三个月 AI Agent 实战学习】Day 28:项目 —— 网络爬虫 Agent

Day 28:项目 —— 网络爬虫 Agent

欢迎来到第二十八天!今天我们将综合运用前面所学的 Agent 知识,构建一个真正实用的网络爬虫 Agent。这个 Agent 能够接收用户提供的网址,自动抓取网页内容,并调用大模型生成简洁的摘要。通过这个项目,你将学会如何将外部网络请求封装为工具,如何处理网页内容的提取与清洗,以及如何让 Agent 在真实场景中自主决策。


一、今日学习目标

  1. 掌握使用requests和BeautifulSoup抓取网页内容的基本方法。
  2. 学会将网页抓取功能封装为 LangChain 工具,供 Agent 调用。
  3. 处理网络请求中的常见问题:超时、编码、非 HTML 内容、反爬虫等。
  4. 构建一个 ReAct Agent,使其能够根据用户输入的网址,自主调用抓取工具并生成摘要。
  5. 理解真实项目中工具设计需考虑的鲁棒性。

二、详细实现步骤

步骤 1:安装依赖并准备环境

首先确保你的虚拟环境中已安装requests和beautifulsoup4。如果尚未安装,执行:

pipinstallrequests beautifulsoup4

同时,确认之前已安装langchain、langchain-openai等库。

新建web_scraper_agent.py,导入所需模块:

importosimportrequestsfrombs4importBeautifulSoupfromdotenvimportload_dotenvfromlangchain_openaiimportChatOpenAIfromlangchain_core.toolsimporttoolfromlangchain.agentsimportcreate_react_agent,AgentExecutorfromlangchain_core.promptsimportPromptTemplatefromtypingimportAnnotated load_dotenv()# 初始化 LLMllm=ChatOpenAI(model="deepseek-chat",api_key=os.getenv("DEEPSEEK_API_KEY"),base_url="https://api.deepseek.com",temperature=0.3)
步骤 2:定义网页抓取工具

我们定义一个工具函数fetch_webpage,它接收一个 URL,返回网页的纯文本内容。这个工具需要处理:

  • HTTP 请求超时(设置合理超时时间)
  • 状态码错误(如 404、500)
  • 编码问题(尝试从响应头或内容中获取编码)
  • 非 HTML 内容(如 PDF、图片,直接返回提示)
  • 网页太大(截取前 N 字符,避免上下文溢出)
  • 反爬虫(模拟 User-Agent)
@tooldeffetch_webpage(url:Annotated[str,"要抓取的网页完整 URL,例如 https://example.com"])->str:"""抓取指定网页的正文文本内容,用于后续摘要或信息提取。返回网页的纯文本,如果失败则返回错误信息。"""headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"}try:# 发送 GET 请求,设置超时resp=requests.get(url,headers=headers,timeout=10)resp.raise_for_status()# 如果状态码不是 2xx,抛出异常exceptrequests.exceptions.Timeout:return"错误:请求超时,请检查网址是否正确或稍后重试。"exceptrequests.exceptions.ConnectionError:return"错误:无法连接到服务器,请检查网址或网络。"exceptrequests.exceptions.HTTPErrorase:returnf"错误:HTTP 错误,状态码{resp.status_code}。"exceptExceptionase:returnf"错误:请求失败,{e}"# 检查内容类型content_type=resp.headers.get("Content-Type","")if"text/html"notincontent_typeand"text/plain"notincontent_type:returnf"错误:网址返回的不是 HTML 或文本内容(Content-Type:{content_type}),无法提取。"# 处理编码ifresp.encodingisNoneorresp.encoding.lower()=='iso-8859-1':# 尝试从内容中检测编码resp.encoding=resp.apparent_encoding# 使用 BeautifulSoup 解析 HTMLsoup=BeautifulSoup(resp.text,"html.parser")# 移除脚本和样式标签forscriptinsoup(["script","style","nav","footer","header"]):script.decompose()# 提取正文文本text=soup.get_text(separator="\n",strip=True)# 截取前 8000 字符,避免内容过长max_length=8000iflen(text)>max_length:text=text[:max_length]+"\n...(内容过长,已截断)"returntext

说明:

  • 使用Annotated为参数url提供描述。
  • docstring 详细描述了工具功能、输入和输出,以及可能的错误情况。
  • 设置了合理的请求头,模拟浏览器。
  • 使用resp.raise_for_status()快速检查 HTTP 错误。
  • 处理了编码问题,使用apparent_encoding自动检测。
  • 移除了常见的非正文标签。
  • 截断长文本,防止 Token 超限。
步骤 3:创建 ReAct Agent

使用与 Day 24 类似的 ReAct 提示词模板和create_react_agent。

react_template="""你是一个智能助手,可以通过调用工具来回答用户问题。你可以使用以下工具: {tools} 工具名称列表:{tool_names} 使用以下格式进行推理和行动: 问题:用户提出的问题 思考:你应该思考接下来要做什么 行动:要使用的工具名称,必须是 [{tool_names}] 中的一个 行动输入:传递给工具的输入 观察:工具返回的结果 ...(这个思考/行动/行动输入/观察可以重复 N 次) 思考:我现在知道最终答案了 最终答案:对用户问题的最终回答 开始! 问题:{input} 思考:{agent_scratchpad}"""prompt=PromptTemplate.from_template(react_template)# 创建 Agentagent=create_react_agent(llm,[fetch_webpage],prompt)# 创建执行器agent_executor=AgentExecutor(agent=agent,tools=[fetch_webpage],verbose=True,# 显示详细过程handle_parsing_errors=True,max_iterations=5)
步骤 4:测试 Agent

运行以下测试用例,观察 Agent 的行为:

if__name__=="__main__":# 测试 1:正常网页摘要result=agent_executor.invoke({"input":"请抓取 https://www.example.com 的内容并总结要点"})print("最终答案:",result["output"])# 测试 2:无效网址result2=agent_executor.invoke({"input":"请抓取 https://this-is-a-fake-url-that-does-not-exist.com 并总结"})print("最终答案:",result2["output"])

运行后,你会看到 Agent 先思考需要抓取网页,然后调用fetch_webpage,得到网页文本,最后根据文本生成摘要。对于无效网址,工具返回错误信息,Agent 会理解错误并告知用户无法访问。

步骤 5:优化与扩展
  • 如果希望 Agent 在摘要前先确认网页是否有效,可以在工具中返回更详细的错误分类。
  • 可以添加一个summarize_text工具,但摘要由 LLM 直接完成即可。
  • 如果需要抓取多个网页,Agent 可以在循环中多次调用工具。

三、常见问题与调试

Q1:网页编码乱码怎么办?
→ 在requests中设置resp.encoding = resp.apparent_encoding通常能解决大部分中文网页的编码问题。如果仍有乱码,可以尝试在BeautifulSoup构造时传入from_encoding参数。

Q2:请求被目标网站拒绝(403 Forbidden)。
→ 网站可能检测到非浏览器请求。可以尝试更换更完整的 User-Agent,或者添加其他请求头(如 Accept、Referer)。但请注意尊重网站的 robots.txt 和服务条款,不要频繁抓取。

Q3:网页内容太大,截断后可能丢失重要信息。
→ 可以只提取正文的特定部分(如文章主体),使用更智能的正文提取库(如readability-lxml)。但作为演示,截断前 8000 字符已经足够。实际项目中可根据需要调整长度。

Q4:BeautifulSoup 的get_text()提取出的文本包含大量空白和换行。
→ 我们使用了strip=True和separator="\n"来清理,但可能仍有连续换行。可以在返回前用正则替换多余空白:

importre text=re.sub(r'\n\s*\n','\n\n',text)

Q5:Agent 在得到网页内容后,摘要生成质量不高。
→ 可以降低 LLM 温度,或在提示词中要求“提取关键信息,忽略广告和无关内容”。另外,截取的文本长度影响摘要质量,可以适当增加。

Q6:如何让 Agent 只抓取特定网站的链接?
→ 可以在工具描述中加入限制,例如“只抓取 example.com 域下的页面”,并在工具内部检查 URL 的域名。


四、今日总结与作业

今天你完成了:

  • ✅ 使用requests和BeautifulSoup实现了网页抓取功能。
  • ✅ 将抓取功能封装为 LangChain 工具,并处理了多种网络错误。
  • ✅ 构建了一个完整的 ReAct Agent,能够根据用户提供的网址自动抓取并生成摘要。
  • ✅ 通过测试验证了 Agent 在正常情况和异常情况下的表现。

今日作业(必做):

  1. 在fetch_webpage工具中添加对 PDF 链接的检测(如果 URL 以.pdf结尾,返回提示“不支持 PDF 文件”)。
  2. 修改工具,使其只提取网页中的<article>或<main>标签内容(如果存在),否则回退到整个正文。观察提取质量是否提高。
  3. 尝试让 Agent 抓取一个新闻网页(例如 BBC 中文网的一篇文章),并让它用中文总结出 3 个要点。记录 Agent 的完整执行过程。
  4. (思考题)如果目标网页需要登录或包含动态加载的内容(JavaScript 渲染),你会如何扩展这个 Agent?请简述你的方案。

明日预告:我们将进入 RAG 的优化阶段,学习如何通过更合理的文档切分和检索策略来提升 RAG 的效果,为构建更强大的 Agent 记忆模块做准备。

有任何问题欢迎随时提问!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 2:46:26

秘书学毕业论文怎么写?公文、沟通和行政事务案例怎么避免写成“工作经验总结”

秘书学毕业论文怎么写&#xff1f;公文、沟通和行政事务案例怎么避免写成“工作经验总结” 秘书学毕业论文最容易写成岗位经验总结&#xff1a;秘书要提高沟通能力、做好公文写作、加强时间管理。问题是这些结论几乎适用于所有办公室岗位&#xff0c;如果没有真实公文、流程、访…

作者头像 李华
网站建设 2026/10/6 2:46:22

2026年合肥靠谱会务服务商推荐与选择指南

在合肥办会&#xff0c;如果只推荐一家会务公司&#xff0c;斯百德会展是值得优先考察的对象。这家由科大校友于2007年创立的企业&#xff0c;深耕会议展览行业十余年&#xff0c;累计服务各类会议、展览及赛事近千场&#xff0c;持有国家高新技术企业、安徽省专精特新中小企业…

作者头像 李华
网站建设 2026/10/6 2:46:21

Doris 4.1 从理论到实践 —— 第 6 章 物化视图与分层建模

Doris 4.1 从理论到实践 —— 第 6 章 物化视图与分层建模 课程定位:本章把第 5 章的"单点加速"提升到"链路加速"。从数仓分层方法论出发,用 Doris 4.1 的同步单表 + 异步多表物化视图把 ODS → DWD → DWS → ADS 四层串联成一张车联网实时数仓分层蓝图…

作者头像 李华
网站建设 2026/10/6 2:45:23

DFT覆盖率度量与测试质量评估体系

DFT覆盖率度量与测试质量评估体系 DFT(Design for Testability,可测性设计)覆盖率度量是集成电路测试领域最核心、也最容易被误解的话题之一。一位资深IC测试工程师面对流片回来的第一颗芯片,他真正关心的问题并不是"测试集跑了多少条pattern",而是"这套测…

作者头像 李华
网站建设 2026/10/6 2:43:41

20262809 2026-2027-1 《Linux内核原理与分析》第八周作业

从 execve 到新入口&#xff1a;Linux 如何装载并启动 ELF 程序 课程&#xff1a;《Linux内核原理与分析》 **实验&#xff1a;**实验七&#xff08;第八周&#xff09; **姓名&#xff1a;**叶丁再 **学号&#xff1a;**20262809 **日期&#xff1a;**2026 年 9 月 27 日 一…

作者头像 李华
网站建设 2026/10/6 2:43:16

AI 生成会议纪要好用吗?多款 APP 功能分析

AI 生成会议纪要已经成为办公记录的常见方式&#xff0c;但不同工具在模板能力、转写约束、数据处理逻辑上差异明显&#xff0c;很多使用者会遇到纪要框架单一、行业内容适配不足、长音频整理混乱等实际问题。选取通义听悟和科会通&#xff0c;围绕会议纪要生成相关能力做功能对…

作者头像 李华