AgentWebSearch 实测:一个只用 Python 标准库的 Web 搜索技能
一、为什么写这个
做 Agent 的时候有个常见套路:让模型联网查资料。要么走第三方 API(要 API Key、要钱、有配额),要么自己写爬虫(要装 requests、要装 BeautifulSoup、要处理反爬)。第三种思路一直存在但很少人提:只靠 Python 标准库能不能做一个能用的 Web 搜索?
我在 GitCode 上翻到一个 40 星的小项目 AgentWebSearch,作者是社区贡献者,核心就是一个 277 行的 web_search.py,只 import 标准库。我把它 clone 下来实跑了一遍,看看这个"零依赖"的承诺到底站不站得住。
二、它怎么实现的
三个入口,都在一个文件里:
web_search(query, limit)→ 文本搜索fetch_webpage(url)→ 抓正文纯文本search_images(query, limit, output_dir)→ 搜图并下载到本地
搜索走的是 cn.bing.com,User-Agent 伪装成 Chrome 120。解析思路简单粗暴——用两条正则把 Bing 搜索结果页里 <h2><a> 块和 <p class="b_lineclamp"> 块分别抠出来。整个项目不出现 import requests、import bs4,一个都没有。
三、真跑
Python 3.14.3 环境。先把三个命令都跑一遍。
文本搜索:
$ python web_search.py search "Python 3.14 新特性" --limit 3
1. Welcome to Python.org
URL: https://www.python.org/
摘要: The mission of the Python Software Foundation is to promote...
2. Download Python | Python.org
URL: https://www.python.org/downloads/
摘要: Starting with the Python 3.11.0, Python 3.10.7...
3. 欢迎来到 Python.org - Python 编程语言
URL: https://pythonlang.cn/
摘要: 2026年9月29日 · 快速 & 易于学习...
网页抓取:
$ python web_search.py fetch "https://python.org/about/" | head -c 500
About Python™ | Python.org Notice: This page displays a fallback because
interactive scripts did not run...
图片下载:
$ python web_search.py images "Python logo" --limit 3 --output ./img
已下载 3 张图片:
./img/Pythonlogo_0.jpg
./img/Pythonlogo_1.jpg
./img/Pythonlogo_2.jpg
零依赖验证:脚本 import 的全部是 urllib.request、urllib.parse、re、json、argparse、html、pathlib、typing,全部标准库。项目里不出现任何第三方 import 语句。
四、我踩到的三个坑
跑通以后我又专门挖了两个非典型场景,一个意外发现了一个真实 bug,一个印证了 Bing 排名的问题。
坑 1:图片扩展名写死,PNG 被存成 .jpg
我用 images "Python logo" --limit 3 下载了三张图,然后用魔数验证真实类型:
Pythonlogo_0.jpg 132,535 B head=ffd8ffe000104a464946 真实类型: JPEG ✓
Pythonlogo_1.jpg 19,633 B head=ffd8ffe000104a464946 真实类型: JPEG ✓
Pythonlogo_2.jpg 319,229 B head=89504e470d0a1a0a0000 真实类型: PNG ✗
第三张其实是 PNG,扩展名却是 .jpg。回头看代码,_download_image 里根据 Content-Type 决定扩展名,返回修正后的路径字符串——但 search_images 循环里先用 .jpg 拼好路径再传给下载函数,返回值只被 append 到列表,从未回写文件名。结果:Content-Type 判断白做了。要修正的话,最简做法是让 _download_image 返回 (path, ext),由调用方再决定文件名。
坑 2:搜英文 PEP,返回中文教材站
$ python web_search.py search "PEP 703 Python 3.14" --limit 2
1. PEP - 人民教育出版社官方网站-培根铸魂 启智增慧
URL: https://www.pep.com.cn/
摘要: 2020年11月30日 · 版权信息 | 联系我们...
2. PEP - 中小学教材电子版
URL: https://jc.pep.com.cn/
摘要: 2026年9月1日 · 提供中小学教材的电子版资源...
搜 PEP 703 返回人民教育出版社——因为 pep.com.cn 的首页标题里也带 PEP 字符,Bing 把它排到了前面。这不是脚本的 bug,是搜索引擎的排序问题。但如果直接把这个结果喂给下游 Agent,就是灾难:Agent 会拿"人民教育出版社"当 PEP 703 去解析。
要治这个,得在解析层加一层过滤——比如把 query 里的核心关键词拆出来,只保留 title 或 snippet 里含关键词的结果。这是这个项目的改进方向,不是它现在的定位。
坑 3:边界处理还算干净
顺便测了两个边界:
$ python web_search.py search "" --limit 3
[错误:请提供搜索关键词]
$ python web_search.py fetch "https://this-domain-does-not-exist-xyz123.com"
[抓取失败: 无法访问该网页]
不过 fetch 这个"无法访问"分支其实也有隐藏问题——网络层错误会被 _http_get 的 except Exception 吞掉,返回 None,再被翻译成 [抓取失败: 无法访问该网页]。DNS 失败和真的"页面不存在"输出完全一样,Agent 分辨不出来。这个静默吞错的模式值得单独讨论:它让"网络故障"和"业务无结果"这两种语义完全不同的失败被压成一个字符串。
五、总结
这个 277 行脚本证明了一件事:不用装任何第三方包,也能有一个能用的 Web 搜索能力。它不是完美的,图片扩展名写死、网络错误被静默吞掉,这两个坑都是真实的。但整体思路值得参考——当 Agent 需要联网能力、又不想背上 requests + bs4 + lxml 一整套时,urllib + re 组合完全够撑一个基础实现。
要用的话记得改两个地方:一是图片扩展名别提前写死,二是网络层错误要向上抛。
(注:AgentWebSearch 由第三方社区贡献者发布,我本文只讨论代码层面观察,不做归属主张。)
- 点赞
- 收藏
- 关注作者
评论(0)