前言
RoboBrowser 是一个确实「小众」的 Python 库,它的自我定位是「不装独立浏览器也能像浏览器一样浏览网页」。它把两个成熟库缝在了一起:用requests处理会话、Cookie 和请求,用 BeautifulSoup 处理 HTML 解析;在此之上又加了一层「浏览器」的心智模型——open()打开页面、follow_link()跟着链接走、get_form()抓表单、submit_form()提交。对于「抓一个没有 API 的老式网站、提交一个搜索框、翻几页用 BeautifulSoup 取数据」这类小任务,它比 Scrapy 轻得多。
但必须提醒一个现实:RoboBrowser 已经很久没有更新了,PyPI 上最新版本是 0.5.3,发布时间停在 2015 年。它依赖的字符集处理方式在新的 Python 3 环境下偶尔会有兼容性摩擦。所以本文的定位是「知道有这么个工具、能用它做点小活儿、也清楚它的边界」,而不是把它推荐去做长期维护的项目。它也是纯 Python 3 时代的库,网上若有人贴出print "..."这类 Python 2 写法,请自行改成print(...);同理.iteritems()→.items()、xrange→range。Python 2.7 早在 2020 年 1 月 1 日就停止维护了。
最后,凡是用它能提交表单的场景,都默认带着「自动化操作」的属性:请只对允许抓取的站点、以合规则频率使用,绝对不要用它去登录不属于你的账号、绕过登录墙或批量提交垃圾内容。
一、它是怎么「像浏览器」的
理解 RoboBrowser,只要记住三点:
- 它内部维护一个持久会话(session),所以 Cookie、重定向、Referer 会像真实浏览器一样在多次请求之间延续。
- 页面打开后,它把 HTML 交给 BeautifulSoup 解析,你因此可以直接用
select()、find_all()这类熟悉的查找方式。 - 表单是一等公民:
get_form()返回一个表单对象,你可以读它的字段、改字段值,再submit_form()提交。
它和几个常见方案的对比如下:
| 方案 | 解析 | 会话/表单 | 调度与并发 | 适合 |
|---|
| urllib | 无 | 无 | 无 | 单次取原文 |
| requests + BeautifulSoup | BeautifulSoup | 手动管 Cookie | 无 | 中小型脚本 |
| RoboBrowser | BeautifulSoup | 内置表单对象 | 无 | 表单流程 + 简单抓取 |
| Scrapy | css/xpath | 内置 | 完整 | 系统性抓取 |
| 无头浏览器 | DOM | 完整交互 | 需自己管 | JS 渲染、复杂交互 |
一句话:RoboBrowser 的甜区是「网站结构老旧、有表单、数据量不大」,抓大站或需要并发调度时应该换工具。
二、打开页面与查找元素
装好之后(pip install robobrowser),最基本的用法是这样:
# 适用于 Python 3,robobrowser 0.5.3
from robobrowser import RoboBrowser
# history=True 会记录访问历史,便于回退
browser = RoboBrowser(history=True, user_agent="robobrowser-demo/0.1 (+https://example.com/bot)")
# 打开一个允许抓取的练习站点
browser.open("https://quotes.toscrape.com/")
# select() 的返回值就是 BeautifulSoup 的查找结果
for quote in browser.select("div.quote"):
text = quote.select_one("span.text")
author = quote.select_one("small.author")
if text and author:
print(author.get_text(strip=True), "|", text.get_text(strip=True))几点说明:user_agent参数让你明确表明自己的爬虫身份,这比伪装成浏览器更诚实,也方便对方在需要时联系你。select()返回的是一个结果列表(对应 BeautifulSoup 的select),select_one()返回单个节点或None。取文本用get_text(strip=True),它能顺手去掉首尾空白——strip=True是关键,否则你会拿到一堆换行和缩进。
如果你想直接拿底层对象,browser.parsed是当前页面的 BeautifulSoup 文档对象,browser.response是最近一次请求的requests响应对象。它们是排查问题时的两个抓手。
三、表单、链接与翻页
RoboBrowser 真正区别于「requests + BeautifulSoup」的地方是表单对象。下面的例子对练习站点的公开搜索表单做填写与提交:
# 适用于 Python 3,robobrowser 0.5.3
from robobrowser import RoboBrowser
browser = RoboBrowser(user_agent="robobrowser-demo/0.1 (+https://example.com/bot)")
browser.open("https://quotes.toscrape.com/")
form = browser.get_form(action="/search")
if form is not None:
# 通过字段名索引到字段,再改它的 value
form["q"].value = "life"
browser.submit_form(form)
for quote in browser.select("div.quote"):
print(quote.select_one("span.text").get_text(strip=True))get_form()可以按action=或class_=之类的属性定位表单;表单对象像字典一样用字段名索引,取到的是字段对象,改值要写.value = ...,而不是直接给字段名赋值。提交用browser.submit_form(form),提交后browser指向响应页面,接着就能select()取数据。
跟链接走用follow_link(),它既接受前面select()出来的节点,也能按链接文本模糊匹配:
# 适用于 Python 3,robobrowser 0.5.3
links = browser.select("li.next a")
if links:
browser.follow_link(links[0]) # 翻到下一页history=True时还可以用browser.back()回退。这些方法的完整参数表以 RoboBrowser 官方文档为准,不同小版本的细节略有差异。
四、边界与合规
RoboBrowser 不做调度、不做去重、不做并发控制,这三件事都得你自己来:要么在循环里手动time.sleep()控制节奏,要么干脆换成 Scrapy。它也不执行 JavaScript,所以对纯前端渲染的页面无能为力。
更重要的是合规边界。表单能力让它看起来像「可以自动登录」的工具,但这不是它该被使用的方向。用自动化脚本登录他人账号、绕过登录后才能访问的内容、或者对表单做批量提交,都属于滥用。正确姿势是:抓之前看目标站点的 robots.txt 和使用条款,只抓公开、允许抓取的内容,保持礼貌的请求间隔。
常见坑点
1. 改表单字段时搞错写法
❌form["q"] = "life",这不会更新字段值,提交时还是空。 ✅form["q"].value = "life",通过字段对象的.value赋值。
2. 把select()当单值用
❌title = browser.select("h1").get_text(),结果是列表,没有get_text。 ✅browser.select_one("h1").get_text(strip=True),或用select(...)[0]。
3. 取文本忘记去空白
❌get_text()拿到"\n Albert Einstein\n ",比较字符串时永远不相等。 ✅get_text(strip=True)。
4. 以为它会执行 JavaScript
❌ 对一个纯前端渲染的页面用 RoboBrowser 抓数据,结果全是空容器。 ✅ 它只解析服务器返回的 HTML;JS 渲染的页面要换无头浏览器方案。
5. 忘了submit_form()之后页面已变
❌ 提交后仍拿提交前的links列表去follow_link,跟到旧页面。 ✅ 提交后重新select(),从新页面取节点。
6. 靠它做自动登录或绕过登录墙
❌ 写脚本自动填账号密码登录他人系统。 ✅ 只对公开页面做抓取;需要授权的数据走官方 API 或申请许可。
7. 拿它做高频批量抓取
❌ 在循环里无间隔地连续open(),给对方服务器压力。 ✅ 手动time.sleep()控制间隔;数据量大就换带调度与限速的框架。
8. 忽略它已经多年未更新
❌ 新项目直接把 RoboBrowser 当中长期依赖。 ✅ 先确认它在新 Python 版本下是否可用,并评估是否有更活跃的替代方案。
总结
| 你能做的事 | 写法 |
|---|
| 打开页面 | browser.open(url) |
| 查找元素 | browser.select(css)/browser.select_one(css) |
| 定位表单 | browser.get_form(action=...) |
| 改字段值 | form["name"].value = ... |
| 提交表单 | browser.submit_form(form) |
| 跟链接 | browser.follow_link(node) |
| 拿底层对象 | browser.parsed/browser.response |
RoboBrowser 的价值在于它的「薄」:语法少、心智简单,几个方法就能完成「打开—找表单—提交—取数据」这条短链路。但它的更新已经停在很多年前,能力边界也很清晰——不并发、不渲染 JS、不做调度。把它当成一把顺手的小刀用在对的地方,而不是当成万能工具箱,才是它最合适的打开方式。