先说明一下:我在实际项目里折腾 DrissionPage 的次数不算少,从最早的 2.x 版本一路用到现在的 4.x,期间踩过的坑、绕过的弯路,比文档里能写出来的多得多的多。今天这篇我把能想到的都整理出来,包括最基础的安装跑通、三个核心 Page 对象怎么选、XPath 语法怎么在自动化脚本里真正落地,以及一批只有实操过才会知道的细节。如果你正准备用 DrissionPage 做 Windows 自动化脚本,或者想给手动重复操作搞个 AI 流程自动化工具出来,这篇可以直接照着抄。
1. 为什么是 DrissionPage:从一次让人崩溃的登录说起
1.1 它解决的最痛问题:登录状态复用
早年间做网页自动化,最让人抓狂的一件事是:Requests 拿不到登录后的数据,Selenium 又慢又笨重。我第一回做某个后台报表下载的时候,用 Requests 模拟登录被各种 JS 加密逼得走投无路,无奈上了 Selenium,绕是绕过去了,但每次跑任务都要重新起一个浏览器、加载全部页面资源,几分钟操作量多则要花上半小时,更难受的是验证码一来整个流程就要当场接管,运维体验基本为零。
DrissionPage 把这个局面整个翻了个个儿。它是基于 Python 的一个自动化库,核心思路是在同一个浏览器会话里同时拿到底层请求能力和浏览器交互能力。你可以先用普通请求方式把页面拿下来,也能随时启动 Chromium 内核去操作页面;重点是登录状态是共享的,不需要再像以前那样手工复制 Cookie、再塞到 Requests 的 headers 里。
这套机制带来的实际好处非常直接:既能用 requests 级别的速度去抓接口数据,又能在需要的时候操作页面上的按钮、输入框、下拉菜单。省去了手动搬运 Cookie 的步骤,登录态复用问题不再存在。我当时第一次在同一会话里先登录再拿数据,简直有“这世界终于清净了”的感觉。
1.2 DrissionPage 和 Selenium、Requests 的定位差异
很多人第一次接触 DrissionPage 会问:我不是已经有 Selenium 了吗?为什么还要学一个新的工具?
这个问题的本质在于三者的设计定位完全不同。
- Requests:只负责发 HTTP 请求,快、轻、灵活,但拿不到 JS 渲染后的内容,遇到需要点击、拖拽、滚动才能触发的逻辑就无能为力。它本质上就是个“没有眼睛也没有手”的数据搬运工。
- Selenium:能打开真实浏览器,模拟人的操作,但太重。每一次操作都要经过 WebDriver 与浏览器之间的通信,步骤一多速度就肉眼可见地慢。而且它对反爬策略的应对能力很弱,经常被网站检测到自动化特征。
- DrissionPage:走的是“浏览器内核控制 + 请求直连”的双轨路线。页面交互依赖 Chromium 内核,数据读写又可以直接走底层请求,识别成自动化特征的概率大幅下降。并且它不需要安装 WebDriver,因为内置的浏览器控制协议直接对接了浏览器内核。
用一个做饭的类比方便你理解:Requests 是只负责把菜端到桌上的服务员,Selenium 是自己开火做饭的厨师,DrissionPage 则既能在后厨颠勺、又能直接翻进货单盘点库存,而且这俩工作还是同一个人同时完成的。
1.3 这篇文章适合谁,你能拿走什么
在读这篇文章之前,先判断一下你是否需要它。
- 如果你经常用 Python 写爬虫,经常因为登录态、JS 渲染、验证码的问题卡壳;
- 如果你想给团队里的报表导出、资料录入、批量审批之类的重复工作做一个能自动跑的脚本;
- 如果你之前看过 DrissionPage 但被 XPath 选择器或者官方文档里略显“抽象”的表述劝退了。
那这篇文章就是给你准备的。我会把“安装—跑通—选对象—写 XPath—实战案例—避坑”整条链路完整走一遍。哪怕你之前没接触过任何自动化框架,跟着写一遍也能跑通一个像样的自动化任务。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与最容易被忽略的安装细节
2.1 用 pip 安装 DrissionPage 的正确姿势
DrissionPage 的安装就一句 pip install drissionpage,但就这么一句,我见过太多人在这一步踩到坑。最常见的问题是什么?版本不匹配。
DrissionPage 的 4.x 版本与 2.x、3.x 在使用上有很大差异,很多老教程写的代码在新版本里已经跑不起来了。尤其很多网上的零散案例还是 2.x 时代的写法,直接拿来粘贴复制大概率报错。
安装时建议用如下方式,锁定最新 4.x 版本:
bash复制pip install drissionpage -U
装完之后验证一下版本,确认是 4.x:
bash复制pip show drissionpage
如果你有多个 Python 环境,记得检查当前终端用的是哪个解释器。这个坑非常基础但极其致命:虚拟环境里装好了,运行脚本时用的却是系统 Python,就会报 ModuleNotFoundError。
2.2 首次运行自动下载浏览器的说明
DrissionPage 4.x 默认用的是 Chromium 内核,但不需要你手动去装 Chromium。它会在首次创建浏览器对象时自动下载 Chromium 浏览器组件(类似 Playwright 的做法)。这个下载过程在国内网络环境下有可能卡住,需要多些耐心,如果实在下载不动,也可以手动指定电脑上已有的 Chrome 路径。
手动指定路径的方式是在初始化浏览器时传入 chromium_path 参数。
python复制from drissionpage import ChromiumPage
page = ChromiumPage(chromium_path="C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe")
当然,如果你没手动指定,DrissionPage 会使用它自己管理的 Chromium 实例,这个实例是隔离运行的,不会影响你平时用的 Chrome。
2.3 第一次跑通自动化脚本
下面这段是最简单的无头浏览器示例,用来验证你是不是装好了:
python复制from drissionpage import ChromiumPage
# 创建浏览器对象
page = ChromiumPage()
# 访问一个网页
page.get("https://www.baidu.com")
# 获取当前页面标题
print(page.title)
# 关闭浏览器
page.quit()
如果控制台打印出了“百度一下,你就知道”之类的标题,说明环境已经通了。如果这里就报错,优先检查版本和浏览器内核下载情况,这两个占了 90% 的首次运行失败原因。
提示:Windows 下建议用 Python 3.9 以上版本。某些低版本 Python 对 4.x 的新语法支持不完整,会导致一些莫名其妙的问题。
3. 核心对象扫盲:SessionPage、ChromiumPage、WebPage 怎么选
DrissionPage 最核心的概念是三个 Page 对象,很多人在最初接触时最大的困惑就是“这三个到底啥区别”。我用大白话把它们的定位讲透。
3.1 ChromiumPage:控制浏览器的“手”
ChromiumPage 是你在做页面级自动化时最常用的对象。它启动一个真实的 Chromium 内核,能够操作浏览器标签页、执行 JavaScript、点击按钮、填写表单、读取页面元素。注意看上面的示例,这个对象下能直接用 .get() 发起访问,也能直接通过 .title 获取标题,不再需要像 Selenium 那样搞 driver.get() + driver.title 的组合。
它对用户的友好程度体现在很多细节上,比如获取元素时可以同时使用 XPath、CSS 选择器、甚至文本内容直接检索;等待元素时可以写“等待某个元素出现再继续”,不用费劲去维护一堆显式等待的轮询逻辑。
当你需要模拟真实用户操作(比如登录一个网站、在线填表、点击下载链接等)时,ChromiumPage 是首选。
3.2 SessionPage:纯请求模式的“眼睛”
SessionPage 不启动浏览器,它走的是纯 HTTP 请求方式,连 Chromium 内核都不需要。它能拿到的数据限于服务端直接返回的 HTML 内容,对于需要 JS 渲染的动态页面就无法处理了。
但你千万别小看它。它最大的价值在于速度。当目标页面的大部分数据是从接口请求中直接返回的,而你要做的事情无非是“拿到 JSON,解析,存库”,那么 SessionPage 比 ChromiumPage 快好几倍,消耗的内存也少得多。适合做高并发数据采集。
python复制from drissionpage import SessionPage
session_page = SessionPage()
session_page.get("https://httpbin.org/html")
print(session_page.html)
这种写法看起来有点像 Requests,但它额外提供了统一的元素查找语法。从 Requests 过渡过来几乎零成本。
3.3 WebPage:请求与浏览器双模式切换的“全能选手”
WebPage 融合了上述两者的能力,并且提供一个 change_mode() 方法,可以在浏览器模式和请求模式之间自由切换。
举个例子:你打开了一个登录后的页面,页面里有个列表是通过 JS 渲染的,你想拿到列表数据。
- 先用浏览器模式打开页面,完成登录;
- 再用
change_mode()切到请求模式,直接获取同样的 URL 的接口数据。
两个模式共享同一个会话(Cookie 等),全程不需要手工搬运任何凭证。
python复制from drissionpage import WebPage
page = WebPage() # 默认浏览器模式
page.get("https://example.com/login")
# 执行登录操作...
# 切到请求模式
page.change_mode() # 现在 page 是 SessionPage
data = page.get("https://example.com/api/data")
print(data.json() if hasattr(data, 'json') else data.text)
这个能力在做“登录后数据采集”的场景中非常实用。我后面要写到的实战案例,本质上就是这个模式的经典应用。
一个很关键的点:用 WebPage 时必须注意,切换模式后,某些操作只能在特定模式下使用。比如
.click()是浏览器模式的方法,在请求模式下就不存在。设计脚本时最好对当前模式保持明确认知。
4. XPath 语法详解:自动化脚本的第一生产力
标题里写的“含 XPath 语法”,说明这是很多初学者最关心的部分。说实话,DrissionPage 的定位虽然是自动化工具,但元素定位的质量直接决定自动化脚本的稳定性。XPath 又是元素定位里功能最强大的一种方式,所以我单独开一个大章节来讲。
4.1 XPath 的绝对路径与相对路径:别再盲目复制绝对路径
XPath 中最基础的概念是路径表达式,它用来在 HTML/XML 文档中定位节点。
绝对路径以 / 开头,从根节点开始完整描述到达目标节点的路径。它最大的问题是脆弱:前端页面稍微改一个层级,脚本就废了。
不推荐这种做法:
text复制/html/body/div[2]/div[1]/div[3]/form/div[1]/input
一旦页面某处多包了一层 div,这个路径就全部失效。
相对路径以 // 开头,表示“不考虑前面的结构,只要匹配到满足条件的元素即可”。这个在实际自动化脚本中是绝对主力。
text复制//input[@id='username']
表示“查找页面里 id 为 username 的 input 元素”,不管它藏在多深的层级里。稳定性明显更高。
4.2 XPath 的核心语法:节点、谓语、函数、通配符
这里我不讲教科书里的所有内容,只讲自动化脚本中最高频的用法。
选取节点
//:相对路径,从整个文档中查找/:绝对路径,从根节点出发.:当前节点..:父节点
谓语条件用方括号 [] 表示“筛选”
比如:
//input[@id='kw']:id 等于 kw 的 input//a[@class='btn']:class 等于 btn 的 a 标签//div[@name='login']//input[@placeholder='请输入用户名']:用 placeholder 属性定位,非常常用。
位置索引
text复制//div[@class='list']/a[1] # 第一个 a
//div[@class='list']/a[last()] # 最后一个 a
//div[@class='list']/a[position()>2] # 第三个以及之后的 a
需要特别提醒:XPath 的索引是从 1 开始的,和编程语言里从 0 开始的数组索引完全不同。别按 Python 的 list[0] 的思维去取第一个元素。
文本与属性函数
这是实战中使用率最高的一类写法。
text():匹配文本内容
text复制//button[text()='立即登录']
contains():包含匹配,适合元素属性或文本中带有动态变化值的情况
text复制//button[contains(text(), '登录')]
//div[contains(@class, 'btn')]
//img[contains(@src, 'logo')]
starts-with():开头匹配
text复制//input[starts-with(@id, 'user_')]
通配符
*:匹配任意元素节点
text复制//div[@class='header']/*
在实际自动化的定位里,* 多数用于辅助定位相对关系,比如“某个节点下的所有子节点”。
轴(Axes)
轴是 XPath 里相对高级的语法,用好了能解决很多刁钻的定位问题。
following-sibling:::选取当前节点之后的所有同级节点preceding-sibling:::选取当前节点之前的所有同级节点parent:::选取当前节点的父节点ancestor:::选取所有祖先节点
举个场景:页面上有个商品价格的元素,它和商品名称是兄弟关系,但价格元素没有明显的 class。这时你可以用名称元素去推断价格。
text复制//span[contains(text(),'iPhone 15')]/following-sibling::span[@class='price']
这种写法,在很多真实页面的自定义数据采集脚本里,比死记硬背绝对路径可靠一百倍。
4.3 在 DrissionPage 中使用 XPath:API 写法与注意事项
在 DrissionPage 里,你不需要像 Selenium 那样先 find_element(By.XPATH, "..."),它提供了简洁到极致的语法。
python复制# 使用 xpath 定位单个元素
ele = page.ele('xpath://button[text()="立即登录"]')
# 定位多个元素
eles = page.eles('xpath://div[@class="list"]/a')
上面 xpath: 前缀是关键,它告诉解析器当前使用 XPath 语法。如果不写这个前缀,DrissionPage 默认会按照自己的智能解析规则查找元素。如果你看到别人代码里写的是 @id='xx' 或者 text(),那是在用 DrissionPage 自有的查找语法,也别奇怪。
还有一点值得注意:DrissionPage 的 .ele() 默认是找到第一个匹配的元素,如果你需要所有符合条件的元素,一定用 .eles()。这两个 API 在脚本里的健壮性差异很大,很多人就是在这里没注意,导致数据漏抓。
4.4 和 CSS 选择器怎么搭配使用
很多老爬虫玩家对 CSS 选择器更熟,例如 div.list > a.btn。CSS 选择器确实语法简洁,但某些场景下 XPath 才是王者。
举个最典型的例子:CSS 选择器无法直接按“元素文本内容”来定位,而 XPath 可以。
text复制//button[contains(text(),'确定')]
这一行代码,在 CSS 选择器里要写成 button:contains("确定"),但 :contains 伪类在标准 CSS 规范里并不存在,很多浏览器内置的 document.querySelector 根本不支持。所以在做按钮点击这类高频操作时,XPath 绝对是第一选择。
DrissionPage 的定位 API 同时支持两种语法,你不需要被迫二选一,而是可以按场景混着用:精确度高、属性独特的场景用 CSS 更顺手;依赖文本内容和节点关系时用 XPath 更强。
4.5 进阶技巧:用 xpath 的 contains() 应对动态属性
我做过一个自动化填表脚本,目标页面每个字段的 id 后缀是一长串随机字符串,每次刷新都会变。用绝对 XPath 根本无法稳定定位,写死就废。
后来就是靠 contains(@id, 'username') 把前缀匹配出来,稳定地解决了问题:
text复制//input[contains(@id, 'username')]
网上有一种常见的错误做法,是把整个 id 值原样复制下来写进 XPath,这种脚本大概率活不过第二次运行。你用 contains 把动态部分剥掉,只保留静态前缀,基本一劳永逸。
5. 实战案例:一个完整的“登录→查数据→下载报告”流程
光讲语法不落地等于白讲。这里我拿一个非常常见的内部系统场景来演示:需要登录后台、翻页查询某个时间段的订单数据,然后把报表下载到本地。这个流程是一个典型的数据采集自动化任务,几乎覆盖了 DrissionPage 和 XPath 的核心用法。
5.1 案例背景与技术选型
假设目标系统是一个企业级后台,登录页有用户名、密码、验证码,登录后是一个数据报表页面,需要选择日期、点击查询、等待结果、点导出按钮,导出一个 Excel 文件。
技术选型上,选 WebPage 而不是 ChromiumPage,为什么?因为“登录”需要浏览器交互,而且验证码可能要人工介入,但登录成功后的“查询结果数据”可能可以通过接口更快拿到。这一单一需求,WebPage 的请求模式和浏览器模式切换能力是最优解。
当然,为了演示直接、容易理解,下面我主要用浏览器模式来跑,这个模式对新手最友好。
5.2 核心流程拆解与代码实现
流程上分五步:
- 启动浏览器,打开登录页
- 输入用户名、密码,处理验证码
- 等待登录成功,跳转到报表页
- 选择日期范围,点击查询,等待数据加载
- 点击导出,等待下载完成
代码实现如下:
python复制import time
from drissionpage import WebPage
# 创建 WebPage 对象,默认浏览器模式
page = WebPage()
# 1. 打开登录页
page.get('https://your-system.com/login')
# 2. 填入账号
page.ele('xpath://input[@name="username"]').input('your_username')
page.ele('xpath://input[@name="password"]').input('your_password')
# 验证码部分:由于验证码可能是图片验证码,这里先暂停,等待人工处理。
# 同时预留一个手动等待时间,或者接入打码平台。
time.sleep(5)
# 3. 点击登录
page.ele('xpath://button[contains(text(), "登 录")]').click()
# 4. 等待跳转到报表页
page.wait.url_change('https://your-system.com/dashboard')
print('登录成功,当前页面:', page.url)
# 5. 选择日期(这里假设页面有起始日期输入框)
start_input = page.ele('xpath://input[@placeholder="开始日期"]')
start_input.input('2024-06-01')
end_input = page.ele('xpath://input[@placeholder="结束日期"]')
end_input.input('2024-06-30')
# 6. 点击查询按钮
page.ele('xpath://button[contains(text(), "查 询")]').click()
# 7. 等待数据表格加载完成
page.wait.ele_displayed('xpath://table[@id="dataTable"]//tr')
# 8. 点击导出按钮
page.ele('xpath://button[contains(text(), "导 出")]').click()
# 9. 若有下载确认框,点击“确定”
confirm_btn = page.ele('xpath://button[contains(text(), "确 定")]')
if confirm_btn:
confirm_btn.click()
print('导出任务已提交,请检查下载目录。')
这里面有多个关键细节值得展开讲一下。
5.3 等待处理:自动化脚本稳定性的生死线
经验不深的人写这类脚本,惯用 time.sleep(3),等一下再去点下一个按钮。这种做法在本地开发时可能很顺,一到服务器上了延迟一变,脚本立刻变得不稳定。
DrissionPage 提供了比较完善的等待机制,文档里叫“等待”,它的设计思路更接近“人”的思维:页面没加载完,就等;元素没出现,就等;URL 没变化,就等。
上面用到的 page.wait.ele_displayed('xpath://...') 就是等待元素可见。这个比 time.sleep() 好用很多:等到了就接着走,等不到就报错,不会因为提前操作导致失败,也不会因为固定 sleep 时间太长拖慢速度。
另外一个 API 是 page.wait.url_change(),语义上就是“直到 URL 变化”再继续执行。这样做登录跳转检测时,比 sleep 好几秒再主动检查要优雅得多。
5.4 识别各种弹窗、iframe 与多标签页
真实的网页自动化中,最容易让人翻车的几件事:iframe 嵌套、弹窗遮挡、新标签页跳转。
iframe 处理
很多管理系统里面,页面主体是嵌在 iframe 里的。如果直接在当前页面查找元素,会得到一个“找不到节点”的结果。DrissionPage 的定位机制在 ele() 时默认只会搜当前文档,不会自动穿越 iframe。
你需要在 iframe 内查找时,先获取框架元素,再在框架内查找:
python复制frame = page.get_frame('xpath://iframe[@id="mainFrame"]')
frame.ele('xpath://input[@name="keyword"]').input('查询内容')
这一点对新手来说是必须绕过去的一道坎。很多人花了一两个小时排查,最后发现是 iframe 问题。
弹窗处理
对于前端 alert 或 confirm 弹窗,DrissionPage 提供了自动接管能力。当页面上出现弹窗时,可以通过 .handle_alert() 来处理:
python复制page.handle_alert()
默认会点掉弹窗的“确定”按钮。如果想取消,可以传参数 accept=False。
多标签页切换
点击某些链接时,网站会新开一个标签页。如果你直接去新页面查找元素,会出现在旧页面里找半天找不到的情况。
python复制page.wait.new_tab() # 等待新标签页出现
page.wait.tab(1).activate() # 切换到第二个标签页
5.5 数据解析与落盘:拿到报告后还要做什么
导出的 Excel 可能直接下载到默认下载目录,也可能返回一个数据接口的 JSON。如果是前者,你可以在代码中指定下载路径:
python复制page.set.download_path('D:\\auto_downloads')
然后点击导出后,使用 page.wait.download_begin() 等待下载开始。
如果是接口 JSON,更推荐切到请求模式去拿。
python复制page.change_mode()
resp = page.get('https://your-system.com/api/report?...')
records = resp.json()['data']
再把 JSON 数据转为本地 CSV 或 Excel,用 pandas 或者 openpyxl 都行。
python复制import pandas as pd
df = pd.DataFrame(records)
df.to_excel('report.xlsx', index=False)
这一套走完,你就拥有一个从登录到下载报表的全自动脚本,后续接上定时任务,就能实现每天自动跑数据。
6. 踩过的坑与性能优化:来自实战的硬经验
6.1 元素定位失败:可能不是 XPath 写错了
我见过最多的“脚本突然失灵”场景,不是代码改了,而是页面改版了。有些前端框架会随机给元素增添 class 或 id 后缀,比如 Vue 项目里的 data-v-xxx 属性。你原本写死的 class 选择器就会失效。
一个极稳的策略是:尽量使用稳定的属性。优先顺序如下:
- 固定的
id(而且确认不是动态生成的 id) name属性placeholder提示文字- 有业务含义的
class子串 - 文本内容(text 或 contains)
这里的第 5 点最稳。很多时候按钮没有 id、没有 name,但它的“文字”是人类可见的,比如“确认提交”。这个时候 XPath 的 text() 和 contains() 就是唯一解。如果按钮文字里还有空格或特殊字符,contains() 能帮我们忽略这些噪音。
6.2 页面加载策略与资源拦截
浏览器控制模式下,页面加载缓慢往往拖慢整个脚本。很多场景下,图片、CSS、字体文件等资源对自动化数据采集毫无意义,完全可以拦截。
DrissionPage 提供页面设置功能,可以直接阻止请求:
python复制page.set.blocked_urls(('*\.png', '*\.jpg', '*\.css', '*\.woff'))
这样浏览器在加载页面时就不会去下载这些资源,对纯数据处理类任务有明显提升。
另外,也可以设置页面加载策略为 none,让脚本不等待页面资源全部加载完就执行:
python复制page.set.load_mode.none()
但注意:使用这个策略后,你要明确目标元素是靠 JS 动态渲染的,不然可能在元素还没出现时就去查找,造成“找不到元素”的误报。
6.3 长时间运行的浏览器资源占用问题
跑定时任务时,浏览器如果一直开着,内存占用会持续上涨。这是 Chromium 内核的通病。我的做法是:不要一个浏览器对象从头跑到尾,能分段的脚本尽量重新创建浏览器对象,跑完一个阶段就 quit() 释放资源。
举一个实际的例子:
python复制def task():
page = WebPage()
page.get('https://your-system.com')
# 执行任务...
page.quit()
# 定时调度时每次重新执行 task,而不是复用同一个浏览器对象
这样即使某个环节内存泄漏,进程重启后也能恢复。
另外一个实用技巧是定期清理浏览器缓存:
python复制page.clear.cache()
尤其是做大量翻页、刷新操作时,缓存增长会拖慢后续请求速度。
6.4 定时任务中的异常处理与重试机制
自动化脚本最怕的不是出错,而是出错后卡在那里一动不动。常见情况是:页面弹了一个未知弹窗,把按钮盖住了,程序在点击时反复超时,最后挂死。
所以建议每个核心操作包一层重试逻辑:
python复制def click_with_retry(page, xpath, max_retry=3):
for i in range(max_retry):
try:
ele = page.ele(xpath)
ele.click()
return True
except Exception as e:
print(f'第 {i+1} 次点击失败:{e}')
page.wait.ele_displayed(xpath)
raise Exception(f'重试 {max_retry} 次仍无法点击元素: {xpath}')
还有一点:用 try/except 捕获异常只是第一步,更关键的兜底是超时机制。DrissionPage 的每个查找操作本身有超时参数可以设置:
python复制page.ele('xpath://...', timeout=10)
超过 10 秒找不到就直接抛异常,不会无限等待下去。把这个超时调小,再配合重试,脚本的鲁棒性就能明显好转。
6.5 并发与多账号场景
如果你要同时跑多个账号、多份任务,DrissionPage 也支持创建多个浏览器上下文,但我的建议是:除非你真的需要同时抓取大量页面,否则不要轻易上并发。
原因有两方面:
- 多浏览器实例同时运行,CPU 和内存开销会成倍增长,对小服务器很不友好;
- 目标网站的反爬策略会更敏感地检测到同一 IP 下的密集访问。
合理的方式是用队列串行处理,或者限制最大并发数(比如 3 个)。同时保证每次任务结束后正常 quit() 释放资源,避免僵尸浏览器进程残留。
7. 一些值得补充使用的进阶功能
前面我们基本把主流程跑通了,但 DrissionPage 的能力远不止这些。如果后续你还想扩展,我挑三个最常用的进阶功能补充一下。
7.1 直接调用 JavaScript
有些页面的交互无法单纯通过点击和输入触发,比如修改元素属性、触发某个自定义事件、强制显示隐藏元素等。这时候可以直接执行 JS。
python复制page.run_js('document.getElementById("btn").click()')
或者强制给一个隐藏元素赋值:
python复制page.run_js('document.querySelector("input[name=phone]").value="13800138000"')
这在处理某些反自动化检测的场景时特别有用。
7.2 截图与元素截图
做自动化任务时,留底是一个很好的习惯。DrissionPage 可以全页截图,也可以单独截某个元素。
python复制page.get_screenshot(path='full_page.png', full_page=True)
ele = page.ele('xpath://div[@class="chart"]')
ele.get_screenshot(path='chart_area.png')
多账户操作、需要操作审查或审计的场景,这个功能能省很多事。出问题的时候,有截图能省掉大量排查时间。
7.3 代理和请求头设置
在需要更换 IP 或伪装请求头的场景中,可以在创建浏览器对象时传入参数:
python复制page = WebPage()
page.set.proxy('http://127.0.0.1:7890')
page.set.headers({'User-Agent': 'Mozilla/5.0 ...'})
当然,常规场景下不要乱动代理,除非你明确知道自己在做什么。代理配置错误会导致所有请求失败,排查起来也非常费劲。
一个比较稳妥的检查方法是先跑一个测试请求:
python复制page.get('https://httpbin.org/ip')
print(page.text)
返回的 IP 如果是代理 IP,说明代理生效;否则就是没设置成功。
7.4 防止浏览器被识别为自动化工具的常见技巧
这个点很多人关心。其实 DrissionPage 在设计上已经比 Selenium 隐蔽得多,它不需要 WebDriver,因此检测 WebDriver 的脚本对它是无效的。但在一些高防护网站上,仍可能检测到 navigator.webdriver 属性或者自动化相关的异常行为。
这里分享几个常用技巧:
- 隐藏自动化特征:
python复制page.set.user_agent('Mozilla/5.0 ...') # 定制 UA
page.run_js('Object.defineProperty(navigator, "webdriver", {get: () => undefined})')
- 模拟人类操作的节奏:不要在两次点击之间保持 0 间隔,用随机停顿更贴近真实。
python复制import random
time.sleep(random.uniform(0.5, 1.5))
- 控制操作频率:短时间密集操作最容易触发反爬策略,适当拉长间隔反而总时间可能更短,因为少了验证码等干扰。
8. 收尾的真心话:工具终究是手段
写到最后,我还是想多说两句真心话。DrissionPage 确实是我用过的最顺手的桌面端 Python 网页自动化工具之一,但它也不是万能的。
遇到极其严苛的前端防护体系,比如动态 token、加密参数、行为验证码等,单纯靠工具层面的操作控制依然可能不够,还需要结合逆向分析、代理池等手段,那就是另一个深水区了。
不过话说回来,你日常遇到的 80% 以上网页自动化需求,用 DrissionPage 都能解决。它把 Requests 的效率和浏览器的交互能力做到了很难得的平衡,再加上简洁到离谱的语法设计和内置的等待体系,对入门者和老手都很友好。
我个人的建议是,先从一个小任务开始,比如自动登录一个系统、抓取一份列表数据,跑通之后再逐步扩展到复杂场景。每加一个环节就检查一下定位稳定性、等待策略和异常处理,这样一套流程下来,你对这个工具的掌握就不会停留在“能跑通”的层面,而是真的能拿来做生产级的自动化系统。
希望这篇整理能让你少走一些我走过的弯路。如果后面你实际动手时发现了什么新的坑,也欢迎回来交流。
