[AI Agent 04]联网搜索
2026/6/10 20:04:26 网站建设 项目流程

代码是AI写的,用的CC接入DS-v4-pro,代码在前文基础上更新,功能包括:对话记忆、Agent 循环、Function Calling、Agent框架 、文件工具、联网搜索

本篇文章仅作为个人学习笔记记录分享

联网搜索

完整代码如下:

""" 联网搜索 Agent —— 让 AI 能查网页 =================================== 基于框架,新增两个联网工具: 1. web_search —— 搜索网页 2. fetch_url —— 抓取网页内容 """ import sys import os sys.stdout.reconfigure(encoding="utf-8") from importlib.util import spec_from_file_location, module_from_spec spec = spec_from_file_location("framework", os.path.join(os.path.dirname(__file__), "04-agent-framework.py")) framework = module_from_spec(spec) spec.loader.exec_module(framework) Agent = framework.Agent TOOL_REGISTRY = framework.TOOL_REGISTRY.copy() # ============================================================ # 新工具1:网页搜索 # ============================================================ def web_search(query: str, max_results: int = 5) -> str: """用 DuckDuckGo 搜索网页,返回标题和链接""" try: from ddgs import DDGS results = [] with DDGS() as ddgs: for r in ddgs.text(query, max_results=max_results): results.append(f"- {r['title']}\n {r['href']}\n {r['body'][:100]}...") if not results: return "没有搜索到相关结果。" return "\n\n".join(results) except Exception as e: return f"搜索失败:{e}" # ============================================================ # 新工具2:抓取网页 # ============================================================ def fetch_url(url: str) -> str: """抓取一个网页的内容(纯文本)""" try: import requests headers = { "User-Agent": "Mozilla/5.0 (compatible; AI-Agent/1.0)" } resp = requests.get(url, headers=headers, timeout=10) resp.raise_for_status() # 简单提取纯文本(去掉 HTML 标签) import re text = re.sub(r"<[^>]+>", "", resp.text) text = re.sub(r"\s+", " ", text) if len(text) > 2000: text = text[:2000] + "...(内容已截断)" return text.strip() except Exception as e: return f"抓取失败:{e}" # ============================================================ # 注册 # ============================================================ TOOL_REGISTRY.update({ "web_search": { "func": web_search, "description": "搜索网页。当需要查找最新信息、新闻、或你不知道的内容时使用。", "parameters": { "type": "object", "properties": { "query": {"type": "string", "description": "搜索关键词"}, "max_results": {"type": "integer", "description": "最多返回几条结果,默认5"}, }, "required": ["query"], }, }, "fetch_url": { "func": fetch_url, "description": "抓取一个网页的详细内容。搜索到感兴趣的链接后,用这个工具打开查看。", "parameters": { "type": "object", "properties": { "url": {"type": "string", "description": "要抓取的网页完整 URL"}, }, "required": ["url"], }, }, }) # ============================================================ # 启动 # ============================================================ if __name__ == "__main__": agent = Agent(system_prompt="你是一个能上网搜索的 AI 助手。当用户问需要最新信息的问题时,用 web_search 搜索。找到感兴趣的结果后,用 fetch_url 打开看详情。用中文回答。") for name, info in TOOL_REGISTRY.items(): agent.add_tool(name, info["func"], info["description"], info["parameters"]) print("=" * 50) print("联网 Agent —— 我能搜索网页了!") print("试试:") print(" '最近有什么科技新闻?'") print(" '帮我查一下今天的天气'") print(" 'Python 3.13 有什么新特性'") print("输入 'quit' 退出,'clear' 清空记忆") print("=" * 50) while True: user_input = input("\n你: ") if user_input.lower() == "quit": print("再见!") break if user_input.lower() == "clear": agent.clear_memory() print("(记忆已清空)") continue reply = agent.chat(user_input) print(f"AI: {reply}")

一、网页搜索工具

1.ddgs是一个第三方python库,封装了DuckDuckGo的搜索API

DDGS()是一个类,DDGS()创建它的一个实例对象,这个实例内部管理着与DuckDuckGo服务的网络连接

query是函数的第一个参数,代表用户要搜索的关键词或短语

def web_search(query: str, max_results: int = 5) -> str: """用 DuckDuckGo 搜索网页,返回标题和链接""" try: from ddgs import DDGS results = [] with DDGS() as ddgs: for r in ddgs.text(query, max_results=max_results): results.append(f"- {r['title']}\n {r['href']}\n {r['body'][:100]}...") if not results: return "没有搜索到相关结果。" return "\n\n".join(results) except Exception as e: return f"搜索失败:{e}"

2.用三引号包裹的不是注释!是函数的docstring(文档字符串),描述了函数的作用

特性注释(#开头)Docstring(三引号字符串)
归属独立行或代码行末尾,不属于任何对象紧跟在函数、类、模块定义后的第一个语句,属于该对象
存储位置不存储,仅用于阅读代码时提示会被存储在__doc__属性中,运行时可以访问
作用范围仅在源代码中可见可通过help()、IDE 提示、.__doc__获取
用途解释代码细节、临时禁用代码等正式文档,描述函数/类/模块的作用、参数、返回值等
语法要求无,任意位置必须是字符串字面量,且紧跟在定义后
"""用 DuckDuckGo 搜索网页,返回标题和链接"""

3.延迟导入,作用是可以加快启动,不需要搜索功能时不加载库,同时减少依赖,即使缺少库程序也能启动

def web_search(query: str, max_results: int = 5) -> str: try: from ddgs import DDGS # 只在需要时导入

二、网页抓取工具

1.requests是一个第三方HTTP 库,用于发送网络请求

headers是一个字典,用于模拟浏览器的请求头,User-Agent(用户代理)HTTP 协议中的一个请求头字段,用于告诉服务器发起请求的客户端是什么类型

resp = requests.get(url, headers=headers, timeout=10)目标 URL发送GET 请求,携带自定义请求头,并设置超时时间为 10 秒,resp.raise_for_status()在非200状态码时抛出异常

import re导入正则表达式模块,resp.text服务器返回的原始HTML的字符串内容,正则表达式r"<[^>]+>"匹配任何以<>开头、>结尾,中间至少一个不是>的字符的字符串,也就是HTML 标签re.sub将所有匹配到的标签替换为空字符串,得到没有标签的文本。

def fetch_url(url: str) -> str: """抓取一个网页的内容(纯文本)""" try: import requests headers = { "User-Agent": "Mozilla/5.0 (compatible; AI-Agent/1.0)" } resp = requests.get(url, headers=headers, timeout=10) resp.raise_for_status() # 简单提取纯文本(去掉 HTML 标签) import re text = re.sub(r"<[^>]+>", "", resp.text) text = re.sub(r"\s+", " ", text) if len(text) > 2000: text = text[:2000] + "...(内容已截断)" return text.strip() except Exception as e: return f"抓取失败:{e}"

2.Pythonrequests库默认的User-Agentpython-requests/版本号,这个字符串会被服务器识别为一个脚本,很多网站会直接拒绝访问或者其他,为了避免被当作“恶意爬虫”而屏蔽,通常需要伪装成浏览器,所以手动设置User-Agent

Mozilla/5.0代表兼容标记 ,几乎所有浏览器都保留Mozilla/5.0以通过某些旧网站的检测。(compatible; AI-Agent/1.0)是注释,其中的compatible表示兼容,AI-Agent/1.0是自定义名称和版本号,表明这是一个 AI 代理工具。符合网络爬虫或 AI Agent 抓取网页时“礼貌且尽量不触发反爬”的常见实践:自定义 UA,声明身份,同时模拟浏览器基础特征。

import requests headers = { "User-Agent": "Mozilla/5.0 (compatible; AI-Agent/1.0)" }

3.关于re正则表达式

r"..."表示不对字符串内的反斜杠\进行转义处理,而是按字面意思原样保留

普通的字符串方法只能处理固定的、字面意义的文本。而正则表达式允许定义一种规则,然后让Python找出字符串中符合该规则的所有部分。正则表达式定义规则:

\d代表一个数字

\s代表一个空白字符(空格、换行等)

[0-9]代表一个数字(等价于\d

[^>]代表除了>以外的任意字符

+表示前面的字符或组出现至少一次

*表示出现零次或多次

import re text = re.sub(r"<[^>]+>", "", resp.text)

4.正则r"\s+"匹配一个或多个空白字符,将所有连续空白替换成单个空格,使得原本多行、缩进的文本会被压缩成一行

text = re.sub(r"\s+", " ", text)

5.删除字符串开头和结尾的空白字符空格、换行等空白字符

return text.strip()

三、工具注册

1."max_results": {"type": "integer", "description": "最多返回几条结果,默认5"}中的integer即为int,类型一定为整数

TOOL_REGISTRY.update({ "web_search": { "func": web_search, "description": "搜索网页。当需要查找最新信息、新闻、或你不知道的内容时使用。", "parameters": { "type": "object", "properties": { "query": {"type": "string", "description": "搜索关键词"}, "max_results": {"type": "integer", "description": "最多返回几条结果,默认5"}, }, "required": ["query"], # max_results 可选 }, }, # ... fetch_url 类似 })

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询