第 1 章:初识 DrissionPage
1.1 什么是 DrissionPage?核心特点与优势
| 概念名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
| DrissionPage | 自动化工具库 | 集成基于浏览器控制和 requests 请求的网页自动化工具 | from DrissionPage import ChromiumPage | 适用于爬虫、测试、自动化操作 |
| 核心理念 | 控制浏览器 + 模拟请求 | 结合浏览器真实渲染与高效网络请求 | 可在 ChromiumPage 和 SessionPage 间切换 | 提升效率与稳定性 |
| 内核集成 | 内置下载和管理浏览器驱动 | 无需手动配置 chromedriver | page = ChromiumPage() 自动调用驱动 | 支持主流 Chrome 版本 |
| 上手简单 | 面向对象设计,API 简洁 | 降低学习成本,提升开发效率 | page.get('https://www.baidu.com') | 方法命名直观,易于记忆 |
| 兼容性强 | 支持 Python 3.7+ | 适配多种操作系统(Windows、macOS、Linux) | 跨平台运行无需修改代码 | 注意系统权限和路径差异 |
1.2 安装与环境配置(Python、浏览器、驱动)
| 方法/命令名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
| pip 安装 | pip install DrissionPage | 安装 DrissionPage 主库 | pip install DrissionPage | 建议在虚拟环境中安装 |
| 浏览器要求 | Google Chrome 浏览器 | DrissionPage 默认控制 Chrome 浏览器 | 下载并安装最新版 Chrome | 其他 Chromium 内核浏览器也可用 |
| 驱动管理 | 内置 DriverManager | 自动下载并匹配 chromedriver 版本 | 无需手动操作 | 首次运行时自动完成 |
| 检查安装 | python -c "from DrissionPage import *" | 验证是否安装成功 | python -c "from DrissionPage import ChromiumPage; print('OK')" | 出现错误需检查 Python 环境 |
| 升级库 | pip install -U DrissionPage | 升级到最新版本 | pip install -U DrissionPage | 获取新功能和修复 |
| 离线安装 | pip install DrissionPage-xx.whl | 无网络环境下安装 | pip install DrissionPage-4.0.0-py3-none-any.whl | 从官网或 PyPI 下载 whl 文件 |
1.3 第一个自动化脚本:打开网页并关闭
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
ChromiumPage() | page = ChromiumPage() | 创建浏览器页面对象 | from DrissionPage import ChromiumPage / page = ChromiumPage() | 自动启动 Chrome 浏览器 |
get() 方法 | page.get(url) | 打开指定网址 | page.get('https://www.baidu.com') | 等待页面加载完成 |
close() 方法 | page.close() | 关闭当前标签页 | page.close() | 若仅剩一个标签页,浏览器可能退出 |
quit() 方法 | page.quit() | 完全退出浏览器进程 | page.quit() | 推荐在脚本结束时调用,释放资源 |
| 基础脚本结构 | 导入 → 创建 → 操作 → 关闭 | 构建自动化脚本的标准流程 | 见下方代码示例 | 确保 quit() 被调用,避免残留进程 |
from DrissionPage import ChromiumPage
page = ChromiumPage()
page.get('https://httpbin.org')
page.quit()
1.4 核心对象概述:SessionPage 与 ChromiumPage
| 对象/类名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
SessionPage | SessionPage() | 基于 requests 的页面类,模拟 HTTP 请求 | from DrissionPage import SessionPage / page = SessionPage() / page.get('https://httpbin.org/get') | 不打开浏览器,速度快 |
ChromiumPage | ChromiumPage() | 控制真实浏览器,支持页面交互 | from DrissionPage import ChromiumPage / page = ChromiumPage() / page.get('https://www.baidu.com') | 支持 JavaScript 渲染和用户操作 |
| 使用场景对比 | 无 UI / 有 UI | 根据需求选择合适对象 | 爬取静态数据用 SessionPage,操作登录、点击用 ChromiumPage | 可在同一项目中混合使用 |
| 切换模式 | page = ChromiumPage() → SessionPage() | 动态切换控制方式 | session_page = page.as_session() | ChromiumPage 可转为 SessionPage 复用 cookies |
as_session() | page.as_session() | 将浏览器会话转为 SessionPage | page.get('https://login.com') / sp = page.as_session() | 保持登录状态进行高效请求 |
| 页面模式选择 | 根据任务类型决定 | 平衡效率与功能需求 | 大量数据抓取:SessionPage;复杂交互:ChromiumPage | 合理组合可提升整体性能 |
第 2 章:页面对象与基本操作
2.1 SessionPage:基于 requests 的页面操作
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
SessionPage() | page = SessionPage() | 创建基于 requests 的页面对象 | from DrissionPage import SessionPage / page = SessionPage() | 不启动浏览器,适合静态数据抓取 |
get() 方法 | page.get(url) | 发起 GET 请求获取页面 | page.get('https://httpbin.org/get') | 自动处理响应编码 |
post() 方法 | page.post(url, data) | 发起 POST 请求提交数据 | page.post('https://httpbin.org/post', data={'key': 'value'}) | 支持 data、json 参数 |
set_headers() | page.set_headers(headers) | 设置全局请求头 | headers = {'User-Agent': 'Custom'} / page.set_headers(headers) | 对后续所有请求生效 |
cookies_to_dict() | page.cookies_to_dict() | 获取当前会话的 cookies | cookies = page.cookies_to_dict() | 用于身份验证状态保持 |
timeout 参数 | page.get(url, timeout=10) | 设置请求超时时间(秒) | page.get('https://slow-site.com', timeout=5) | 防止请求长时间阻塞 |
2.2 ChromiumPage:控制真实浏览器
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
ChromiumPage() | page = ChromiumPage() | 启动并控制 Chrome 浏览器 | from DrissionPage import ChromiumPage / page = ChromiumPage() | 自动匹配 chromedriver |
new_tab() | page.new_tab(url) | 新建标签页并打开指定网址 | page.new_tab('https://www.qq.com') | 可管理多个标签页 |
get_tab() | page.get_tab(tab_id) | 切换到指定标签页 | tab = page.get_tab(1) # 第二个标签页 | 支持索引或标题匹配 |
close_current_tab() | page.close_current_tab() | 关闭当前标签页 | page.close_current_tab() | 不会关闭整个浏览器 |
set_window_size() | page.set_window_size(w, h) | 设置浏览器窗口大小 | page.set_window_size(1200, 800) | 用于响应式测试 |
hide() / show() | page.hide(); page.show() | 隐藏或显示浏览器窗口 | page.hide() # 转为后台运行 | 适合无头模式替代方案 |
2.3 页面导航:打开、刷新、前进、后退
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
get() 方法 | page.get(url) | 打开或跳转到指定网址 | page.get('https://www.google.com') | 两种页面对象均支持 |
refresh() | page.refresh() | 刷新当前页面 | page.refresh() | 等同于浏览器 F5 |
back() 方法 | page.back() | 返回上一页面 | page.back() | 前进记录存在时才有效 |
forward() | page.forward() | 前进到下一页面 | page.forward() | 配合 back 使用实现导航 |
wait() 方法 | page.wait(timeout=10) | 等待页面加载完成 | page.get('https://slow.com') / page.wait(5) | 确保页面完全加载 |
stop_loading() | page.stop_loading() | 停止当前页面加载 | page.stop_loading() | 用于超时或手动中断 |
2.4 页面信息获取:标题、URL、HTML
| 属性/方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
title 属性 | page.title | 获取当前页面标题 | print(page.title) | 动态页面可能变化 |
url 属性 | page.url | 获取当前页面完整 URL | current_url = page.url | 包含参数和锚点 |
html 属性 | page.html | 获取页面当前 HTML 源码 | html_content = page.html | 包含 JavaScript 渲染后的内容 |
json 属性 | page.json | 解析响应为 JSON(适用于 API) | page.get('https://httpbin.org/json') / data = page.json | 仅当响应为 JSON 格式时有效 |
base_url 属性 | page.base_url | 获取页面基础 URL | base = page.base_url | 不包含路径和参数 |
page_type 属性 | page.page_type | 返回页面类型(‘Chromium’ 或 ‘Session’) | print(page.page_type) | 用于条件判断或日志记录 |
第 3 章:元素定位与交互
3.1 元素定位方法:css、xpath、id、class 等
| 定位方式 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
| id 定位 | '#id_value' | 通过元素 id 属性定位 | page.ele('#username') | id 具有唯一性,优先使用 |
| class 定位 | '.class_name' | 通过 class 名称定位 | page.ele('.btn-primary') | 支持多个 class 组合,如 .a.b |
| 标签名定位 | 'tag_name' | 通过 HTML 标签名定位 | page.ele('input') | 通常需配合属性进一步筛选 |
| css 选择器 | 支持完整 CSS 语法 | 灵活组合属性进行定位 | page.ele('input[name="email"]') | 支持层级、伪类等复杂选择器 |
| xpath 定位 | xpath://表达式 | 使用 XPath 路径定位元素 | page.ele('xpath://div[@class="menu"]/a') | 适合结构复杂或无明确属性的元素 |
| 文本定位 | 'text=文本内容' | 通过元素显示文本定位 | page.ele('text=登录') | 支持精确匹配和模糊匹配(@text) |
| 属性定位 | '[attr=value]' | 通过任意属性值定位 | page.ele('[data-testid="submit"]') | 适用于自定义属性或 aria 标签 |
3.2 元素查找:ele() 与 eles()
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
ele() 方法 | page.ele(loc) | 查找第一个匹配的元素 | user_input = page.ele('#username') | 找不到时返回 None(可设置等待) |
eles() 方法 | page.eles(loc) | 查找所有匹配的元素,返回列表 | items = page.eles('.list-item') | 列表可能为空,使用前应判断长度 |
timeout 参数 | page.ele(loc, timeout=5) | 设置查找超时时间 | btn = page.ele('text=提交', timeout=3) | 超时后抛出异常或返回 None |
| 第二参数为属性 | page.ele(loc, attr) | 直接获取元素指定属性值 | href = page.ele('a', 'href') | 简化操作,避免链式调用 |
| 在元素内查找 | parent.ele(loc) | 在已定位元素内部查找子元素 | form = page.ele('#login-form') / user = form.ele('[name="user"]') | 提高定位精度,减少全局搜索 |
| 动态等待 | ele() 自动等待元素出现 | 配合页面加载自动重试 | page.ele('xpath=//table//tr[1]') | 若元素异步加载,可避免手动 sleep |
3.3 元素操作:点击、输入、清空、获取属性
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
click() 方法 | ele.click() | 模拟鼠标点击元素 | login_btn = page.ele('#login') / login_btn.click() | 确保元素可见且可点击 |
input() 方法 | ele.input(text) | 向输入框输入文本 | user_input.input('myuser') | 支持模拟真实键盘输入 |
clear() 方法 | ele.clear() | 清空输入框内容 | ele.clear() | 建议在 input 前调用,避免残留文本 |
attr() 方法 | ele.attr('href') | 获取元素指定属性值 | link = ele.attr('href') | 属性不存在时返回 None |
text 属性 | ele.text | 获取元素的文本内容 | print(ele.text) | 不包含隐藏元素的文本 |
set_attr() 方法 | ele.set_attr('value', 'new') | 设置元素属性(高级用法) | ele.set_attr('disabled', None) | 可用于绕过前端限制(谨慎使用) |
innerHTML | ele.html | 获取元素内部 HTML | content = ele.html | 包含子元素的完整结构 |
3.4 等待机制:wait.ele_displayed() 等
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
wait.ele_displayed() | wait.ele_displayed(loc) | 等待元素在页面中显示 | page.wait.ele_displayed('#loading', timeout=5) | 常用于等待异步加载完成 |
wait.ele_not_exists() | wait.ele_not_exists(loc) | 等待元素消失(如加载动画) | page.wait.ele_not_exists('.spinner') | 避免因遮罩层导致操作失败 |
wait.download_begin() | wait.download_begin() | 等待下载开始 | page.wait.download_begin() / page.ele('#download').click() | 需在触发下载前调用 |
timeout 参数 | 方法支持 timeout=秒数 | 设置等待最大时长 | page.wait.ele_displayed('text=完成', timeout=10) | 超时后抛出 TimeoutError |
wait.doc_loaded() | wait.doc_loaded() | 等待页面文档加载完成 | page.wait.doc_loaded() | 替代 sleep,更精准 |
| 条件组合 | 配合 while 或 try-except | 实现复杂等待逻辑 | 见下方代码示例 | 自定义等待策略 |
while not page.ele('#ready'):
time.sleep(0.1)
第 4 章:表单处理与高级交互
4.1 表单填写与提交
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
input() 方法 | ele.input('文本') | 向输入框输入内容 | page.ele('#username').input('testuser') | 支持自动触发 input 事件 |
check() 方法 | ele.check() | 勾选复选框(checkbox) | page.ele('[name=agree]').check() | 确保元素为 checkbox 类型 |
uncheck() 方法 | ele.uncheck() | 取消勾选复选框 | page.ele('[name=notify]').uncheck() | 操作前会自动判断是否已选中 |
select() 方法 | ele.select() | 选择单选按钮(radio)或下拉项 | page.ele('[value="male"]').select() | 适用于 type="radio" 元素 |
submit() 方法 | form_ele.submit() | 提交表单(通过 form 元素) | form = page.ele('#login-form') / form.submit() | 触发原生 submit 事件 |
click() 提交 | btn.click() | 点击提交按钮完成表单提交 | page.ele('text=提交').click() | 更常见于现代前端框架 |
fill() 方法 | ele.fill(data_dict) | 批量填写表单字段 | form.fill({'user': 'a', 'pwd': '123'}) | data_dict 键为字段名 |
4.2 下拉选择框(Select)操作
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
select.by_text() | select.by_text('选项文本') | 通过显示文本选择下拉项 | s = page.ele('#city') / s.select.by_text('北京') | 支持部分匹配 |
select.by_value() | select.by_value('value') | 通过 option 的 value 属性选择 | s.select.by_value('sh') | 精确匹配 value 值 |
select.by_index() | select.by_index(1) | 通过索引选择(从 0 开始) | s.select.by_index(2) # 第三个选项 | — |
clear() 方法 | select.clear() | 清除已选中的选项 | s.clear() | 仅适用于多选下拉框 |
is_selected() | option.is_selected() | 判断某选项是否被选中 | if opt.is_selected(): print("已选") | 可用于验证选择结果 |
options 属性 | select.options | 获取所有选项元素列表 | for opt in s.options: print(opt.text) | 便于遍历和分析下拉内容 |
| 多选支持 | select.by_texts([...]) | 同时选择多个选项 | s.select.by_texts(['A', 'B']) | 元素需设置 multiple 属性 |
4.3 文件上传处理
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
input() 方法 | file_input.input('文件路径') | 向文件输入框传入本地文件路径 | page.ele('#file').input('C:/test.pdf') | 自动触发上传 |
| 多文件上传 | input('路径1\n路径2') | 通过换行符分隔多个文件路径 | page.ele('[type=file]').input('a.jpg\nb.png') | 注意路径格式和分隔符 |
| 隐藏文件框处理 | 使用 run_js 显示元素 | 对 display:none 的文件框进行操作 | page.run_js("$('#file').show()") / ele.input('path') | 先使其可操作再上传 |
| 等待上传完成 | 结合 wait 或 ele 判断 | 等待上传成功提示出现 | page.wait.ele_displayed('text=上传成功') | 避免后续操作过早执行 |
| 文件路径格式 | 使用绝对路径 | 推荐使用完整路径避免错误 | path = os.path.abspath('upload.jpg') | 相对路径可能解析失败 |
| 模拟点击触发 | ele.click() + 系统级上传 | 若 input 不可见,可尝试模拟点击弹窗 | 需配合 PyAutoGUI 等工具 | 属高级用法,稳定性较低 |
4.4 鼠标与键盘高级操作(拖拽、组合键)
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
drag_to() | ele.drag_to(target) | 将元素拖拽到目标位置或元素 | src = page.ele('#drag') / dst = page.ele('#drop') / src.drag_to(dst) | 支持拖拽排序、文件上传等场景 |
hover() 方法 | ele.hover() | 模拟鼠标悬停 | menu = page.ele('.dropdown') / menu.hover() | 常用于触发下拉菜单显示 |
press() 方法 | page.press('Tab') | 模拟键盘按键 | page.press('Enter') / page.press('Control+A') | 支持组合键和功能键 |
keys() 方法 | ele.keys('Ctrl+A') | 向元素发送键盘指令 | input_ele.keys('Ctrl+A').keys('Delete') | 可实现全选、删除等操作 |
mouse.click() | page.mouse.click(x, y) | 在指定坐标点击 | page.mouse.click(100, 200) | 适用于无法定位元素的场景 |
mouse.move_to() | page.mouse.move_to(ele) | 将鼠标移动到元素中心 | page.mouse.move_to(btn) | 可用于精细控制鼠标轨迹 |
context_click() | ele.right_click() | 模拟右键点击 | ele.right_click() | 触发上下文菜单 |
第 5 章:页面等待、弹窗与执行脚本
5.1 显式等待与条件判断
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
wait.ele_displayed() | wait.ele_displayed(loc, timeout) | 等待元素在页面中可见 | page.wait.ele_displayed('#load_finish', timeout=10) | 常用于等待异步内容加载 |
wait.ele_not_exists() | wait.ele_not_exists(loc, timeout) | 等待元素消失(如加载动画) | page.wait.ele_not_exists('.spinner') | 避免遮挡后续操作 |
wait.doc_loaded() | wait.doc_loaded() | 等待页面文档完全加载 | page.wait.doc_loaded() | 替代固定 sleep,更精准可靠 |
wait.next_page() | wait.next_page() | 等待页面跳转完成 | page.ele('#goto').click() / page.wait.next_page() | 适用于点击后跳转的场景 |
wait.download_begin() | wait.download_begin() | 等待下载任务开始 | page.wait.download_begin() / page.ele('#download').click() | 必须在触发前调用 |
wait.title() | wait.title('包含文本') | 等待页面标题包含指定内容 | page.wait.title('成功') | 可用于确认操作结果 |
| 自定义等待 | 使用 while + ele() 判断 | 实现复杂条件等待 | 见下方代码示例 | 灵活但需注意超时控制 |
while not page.ele('text=完成'):
time.sleep(0.1)
5.2 JavaScript 脚本执行(run_js)
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
run_js() 方法 | page.run_js('js代码') | 执行 JavaScript 脚本 | result = page.run_js('return document.title') | 可获取或修改页面状态 |
| 修改元素属性 | run_js 设置属性 | 绕过前端限制或隐藏检查 | page.run_js("$('#file').attr('style', '')") | 谨慎使用,避免破坏逻辑 |
| 滚动页面 | 执行 scroll 操作 | 模拟用户滚动 | page.run_js("window.scrollTo(0, document.body.scrollHeight)") | 实现懒加载触发 |
| 注入函数 | 先定义再调用 | 执行复杂逻辑 | page.run_js("function test(){...}") / page.run_js("test()") | 提高脚本复用性 |
| 返回值处理 | js 中 return 值可被接收 | 获取计算结果 | height = page.run_js("return window.innerHeight") | 支持基本数据类型 |
| 操作元素对象 | 传入元素作为参数 | 对特定元素执行操作 | ele = page.ele('#box') / page.run_js("e => e.style.border='2px red'", ele) | ele 自动转换为 DOM 对象 |
| 异步脚本 | 使用 async/await | 执行异步 JS 任务 | page.run_js("await fetch('/api')") | 需确保 Chromium 支持 |
5.3 弹窗处理(alert、confirm、prompt)
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
get_alert() | page.get_alert() | 获取当前弹窗对象 | alert = page.get_alert() | 弹窗出现后立即调用 |
alert.text | alert.text | 获取弹窗显示的文本内容 | print(alert.text) | 可用于验证提示信息 |
alert.accept() | alert.accept() | 点击”确定”关闭弹窗 | alert.accept() | 处理 alert 和 confirm |
alert.dismiss() | alert.dismiss() | 点击”取消”关闭 confirm 或 prompt | alert.dismiss() | 仅适用于 confirm/prompt |
alert.input() | alert.input('文本') | 向 prompt 弹窗输入内容 | alert.input('username') / alert.accept() | 必须先输入再确认 |
| 自动等待弹窗 | 内置机制自动捕获 | DrissionPage 可自动感知弹窗 | 多数情况下无需手动轮询 | 但仍建议显式处理 |
| 异常处理 | try-except 捕获无弹窗情况 | 防止 get_alert() 报错 | 见下方代码示例 | 增强脚本健壮性 |
try:
alert = page.get_alert()
except Exception:
print("无弹窗")
5.4 iframe 与 Shadow DOM 切换
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
switch.to_frame() | switch.to_frame(loc) | 切换到指定 iframe | page.switch.to_frame('#frame1') | 进入 iframe 上下文 |
switch.to_parent() | switch.to_parent() | 切回父级 frame | page.switch.to_parent() | 逐级返回上级框架 |
switch.to_root() | switch.to_root() | 切回主文档(最外层) | page.switch.to_root() | 快速退出所有嵌套 frame |
| iframe 内操作 | 切换后正常调用 ele() 等方法 | 在 iframe 中查找和操作元素 | page.switch.to_frame('iframe') / page.ele('#btn').click() | 当前上下文为 iframe 内容 |
| Shadow DOM 支持 | ele('>>') 语法进入 shadow root | 操作封装的 shadow DOM 元素 | host = page.ele('#host') / inner = host.ele('>>div') | >> 表示进入 shadow root |
| 多层 shadow 嵌套 | 使用多个 >> | 进入深层 shadow 结构 | ele('>> >> span') | 每个 >> 对应一层 shadow root |
| 切换上下文管理 | 注意当前所处的 frame 或 shadow 层级 | 避免元素查找失败 | 操作完成后建议 switch.to_root() | 保证后续操作在正确上下文中 |
第 6 章:实战技巧与性能优化
6.1 多标签页与窗口管理
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
new_tab() 方法 | page.new_tab(url) | 新建标签页并跳转到指定网址 | page.new_tab('https://www.bing.com') | 新标签页成为当前操作上下文 |
get_tab() 方法 | page.get_tab(tab_id_or_url) | 根据索引或 URL 切换到指定标签页 | tab = page.get_tab(1) # 第二个标签页 / tab = page.get_tab('.google.') # 正则匹配 URL | 支持整数索引和正则表达式 |
tabs 属性 | page.tabs | 获取所有标签页对象列表 | for tab in page.tabs: print(tab.title) | 可用于批量操作或状态检查 |
close_current_tab() | page.close_current_tab() | 关闭当前标签页 | page.close_current_tab() | 若仅剩一个标签页,浏览器可能退出 |
set_active_tab() | page.set_active_tab(tab) | 激活指定标签页为当前操作页 | page.set_active_tab(page.tabs[0]) | 与 get_tab 效果类似 |
| 窗口句柄管理 | 内部自动维护 | DrissionPage 自动管理多标签页状态 | 无需手动处理 driver.switch_to.window | 抽象层简化操作 |
| 标签页复用 | 避免频繁新建和关闭 | 提升性能,减少资源开销 | 使用已有标签页执行不同任务 | 建议控制标签页数量防止内存占用过高 |
6.2 下载文件监控与处理
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
set.download_path() | page.set.download_path(path) | 设置默认下载路径 | page.set.download_path('D:/downloads') | 必须在触发下载前设置 |
wait.download_begin() | wait.download_begin() | 等待下载任务开始 | page.wait.download_begin() / page.ele('#download').click() | 返回下载文件名 |
wait.download_finish() | wait.download_finish(filename) | 等待指定文件下载完成 | page.wait.download_finish('report.pdf') | 自动检测文件写入完成 |
| 下载目录配置 | 默认为浏览器默认路径 | 可通过启动参数修改 | 启动时指定 --download.default_directory | 建议统一管理下载目录 |
| 文件重命名检测 | 结合 os.path.exists() 判断 | 监控临时文件转为正式文件 | while not os.path.exists(final_path): time.sleep(0.5) | 防止读取未完成文件 |
| 多文件下载 | 顺序触发并监控 | 处理多个下载请求 | 见下方代码示例 | 注意并发控制和路径区分 |
| 下载失败处理 | 检查文件大小或内容 | 判断下载是否完整 | if os.path.getsize(file) == 0: retry() | 建议添加重试机制 |
for btn in buttons:
page.wait.download_begin()
btn.click()
page.wait.download_finish()
6.3 无头模式与性能调优
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
ChromiumPage(headless=True) | page = ChromiumPage(headless=True) | 启动无头模式浏览器 | page = ChromiumPage(headless=True) | 不显示浏览器窗口,适合后台运行 |
headless 参数 | headless='new' 或 True | 支持新旧版无头模式 | page = ChromiumPage(headless='new') | 'new' 更接近真实浏览器行为 |
set.window_size() | page.set.window_size(w, h) | 设置无头模式下的视口大小 | page.set.window_size(1200, 800) | 影响页面布局和截图效果 |
disable_images() | page.set.load_mode('no_image') | 禁用图片加载提升速度 | page.set.load_mode('normal') # 恢复 | 可显著减少流量和加载时间 |
load_mode 设置 | 'normal', 'light', 'no_image' | 控制页面加载策略 | page.set.load_mode('light') | 轻量模式加快响应 |
| 关闭动画与音频 | 通过启动参数配置 | 减少资源消耗 | page = ChromiumPage(options={'--mute-audio': None}) | 提升运行效率 |
| 最大化资源利用率 | 合理设置并发 Worker | 多任务并行处理 | 结合多进程或线程使用 | 注意系统内存和 CPU 负载 |
6.4 异常处理与日志记录
| 方法名称 | 语法/说明 | 用途 | 代码示例 | 注意事项 |
|---|
| try-except 捕获 | try: ... except Exception as e | 捕获元素未找到、超时等异常 | 见下方代码示例 | 增强脚本稳定性 |
TimeoutError | 来自 wait 操作超时 | 明确识别等待超时异常 | except TimeoutError: log.error("等待元素超时") | 可针对性处理 |
ElementNotFoundError | ele() 查找不到元素时抛出 | 精确识别元素定位失败 | except ElementNotFoundError: handle_missing_element() | 推荐捕获具体异常类型 |
| 自定义日志记录 | 使用 logging 模块输出信息 | 记录关键操作和错误 | import logging / logging.basicConfig(level=logging.INFO) / logging.info("登录成功") | 便于调试和监控 |
| 错误截图 | page.save_screenshot() | 发生异常时保存页面状态 | except Exception: page.save_screenshot('error.png'); raise | 有助于问题排查 |
| 上下文信息输出 | 打印 URL、元素、时间戳 | 提供完整错误上下文 | logging.error(f"URL: {page.url}, 元素: #submit") | 提升可维护性 |
| 异常重试机制 | 结合 time.sleep() 和循环 | 实现失败自动重试 | 见下方代码示例 | 避免因网络波动导致失败 |
try:
page.ele('#btn').click()
except Exception as e:
print(f"操作失败: {e}")
for i in range(3):
try:
# 执行操作
break
except:
time.sleep(1)