
Day 28项目 —— 网络爬虫 Agent欢迎来到第二十八天今天我们将综合运用前面所学的 Agent 知识构建一个真正实用的网络爬虫 Agent。这个 Agent 能够接收用户提供的网址自动抓取网页内容并调用大模型生成简洁的摘要。通过这个项目你将学会如何将外部网络请求封装为工具如何处理网页内容的提取与清洗以及如何让 Agent 在真实场景中自主决策。一、今日学习目标掌握使用requests和BeautifulSoup抓取网页内容的基本方法。学会将网页抓取功能封装为 LangChain 工具供 Agent 调用。处理网络请求中的常见问题超时、编码、非 HTML 内容、反爬虫等。构建一个 ReAct Agent使其能够根据用户输入的网址自主调用抓取工具并生成摘要。理解真实项目中工具设计需考虑的鲁棒性。二、详细实现步骤步骤 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()# 初始化 LLMllmChatOpenAI(modeldeepseek-chat,api_keyos.getenv(DEEPSEEK_API_KEY),base_urlhttps://api.deepseek.com,temperature0.3)步骤 2定义网页抓取工具我们定义一个工具函数fetch_webpage它接收一个 URL返回网页的纯文本内容。这个工具需要处理HTTP 请求超时设置合理超时时间状态码错误如 404、500编码问题尝试从响应头或内容中获取编码非 HTML 内容如 PDF、图片直接返回提示网页太大截取前 N 字符避免上下文溢出反爬虫模拟 User-Agenttooldeffetch_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 请求设置超时resprequests.get(url,headersheaders,timeout10)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_typeresp.headers.get(Content-Type,)iftext/htmlnotincontent_typeandtext/plainnotincontent_type:returnf错误网址返回的不是 HTML 或文本内容Content-Type:{content_type}无法提取。# 处理编码ifresp.encodingisNoneorresp.encoding.lower()iso-8859-1:# 尝试从内容中检测编码resp.encodingresp.apparent_encoding# 使用 BeautifulSoup 解析 HTMLsoupBeautifulSoup(resp.text,html.parser)# 移除脚本和样式标签forscriptinsoup([script,style,nav,footer,header]):script.decompose()# 提取正文文本textsoup.get_text(separator\n,stripTrue)# 截取前 8000 字符避免内容过长max_length8000iflen(text)max_length:texttext[: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}promptPromptTemplate.from_template(react_template)# 创建 Agentagentcreate_react_agent(llm,[fetch_webpage],prompt)# 创建执行器agent_executorAgentExecutor(agentagent,tools[fetch_webpage],verboseTrue,# 显示详细过程handle_parsing_errorsTrue,max_iterations5)步骤 4测试 Agent运行以下测试用例观察 Agent 的行为if__name____main__:# 测试 1正常网页摘要resultagent_executor.invoke({input:请抓取 https://www.example.com 的内容并总结要点})print(最终答案,result[output])# 测试 2无效网址result2agent_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 字符已经足够。实际项目中可根据需要调整长度。Q4BeautifulSoup 的get_text()提取出的文本包含大量空白和换行。→ 我们使用了stripTrue和separator\n来清理但可能仍有连续换行。可以在返回前用正则替换多余空白importre textre.sub(r\n\s*\n,\n\n,text)Q5Agent 在得到网页内容后摘要生成质量不高。→ 可以降低 LLM 温度或在提示词中要求“提取关键信息忽略广告和无关内容”。另外截取的文本长度影响摘要质量可以适当增加。Q6如何让 Agent 只抓取特定网站的链接→ 可以在工具描述中加入限制例如“只抓取 example.com 域下的页面”并在工具内部检查 URL 的域名。四、今日总结与作业今天你完成了✅ 使用requests和BeautifulSoup实现了网页抓取功能。✅ 将抓取功能封装为 LangChain 工具并处理了多种网络错误。✅ 构建了一个完整的 ReAct Agent能够根据用户提供的网址自动抓取并生成摘要。✅ 通过测试验证了 Agent 在正常情况和异常情况下的表现。今日作业必做在fetch_webpage工具中添加对 PDF 链接的检测如果 URL 以.pdf结尾返回提示“不支持 PDF 文件”。修改工具使其只提取网页中的article或main标签内容如果存在否则回退到整个正文。观察提取质量是否提高。尝试让 Agent 抓取一个新闻网页例如 BBC 中文网的一篇文章并让它用中文总结出 3 个要点。记录 Agent 的完整执行过程。思考题如果目标网页需要登录或包含动态加载的内容JavaScript 渲染你会如何扩展这个 Agent请简述你的方案。明日预告我们将进入 RAG 的优化阶段学习如何通过更合理的文档切分和检索策略来提升 RAG 的效果为构建更强大的 Agent 记忆模块做准备。有任何问题欢迎随时提问