1.1 DrissionPage 简介 #
DrissionPage 是一个集成了浏览器自动化与数据包操作的 Python 工具库。它既能像 Selenium 一样控制浏览器,也能像 requests 一样高效收发数据包,并且两种模式可以无缝切换,极大简化了网页自动化和爬虫开发流程。
1.2 安装与环境要求 #
- 操作系统:Windows、Linux 或 Mac
- Python 版本:3.6 及以上
- 支持浏览器:Chromium 内核(如 Chrome、Edge)
安装命令:
pip install DrissionPage升级命令:
pip install DrissionPage --upgrade1.3 导入核心对象 #
DrissionPage 主要有三种页面对象,分别适用于不同场景:
- ChromiumPage:只控制浏览器
- SessionPage:只收发数据包
- WebPage:两者兼备,可随时切换
导入示例:
# 导入 DrissionPage 的三个核心页面对象
# ChromiumPage: 专门用于控制浏览器的页面对象
# SessionPage: 专门用于收发数据包的页面对象
# WebPage: 兼备浏览器控制和数据包功能的页面对象,可随时切换模式
from DrissionPage import ChromiumPage, SessionPage, WebPage1.4 浏览器路径设置(仅首次使用需关注) #
如果你只用数据包功能,无需任何设置。如果要控制浏览器,需确保 DrissionPage 能找到你的 Chrome/Edge 路径。
快速检测:
from DrissionPage import ChromiumPage
page = ChromiumPage()
page.get('http://DrissionPage.cn')如果浏览器能正常启动并访问页面,说明环境已就绪。
如遇找不到浏览器,可用以下方法设置路径:
方法一:Python 脚本设置
# 导入 DrissionPage 的浏览器配置选项类
from DrissionPage import ChromiumOptions
# 设置浏览器路径(请将"你的浏览器路径"替换为实际的浏览器可执行文件路径)
ChromiumOptions().set_browser_path(r'你的浏览器路径').save()
# 设置 Windows 系统下 Chrome 浏览器的默认安装路径
ChromiumOptions().set_browser_path(r'C:\Program Files\Google\Chrome\Application\chrome.exe').save()
# 设置 macOS 系统下 Chrome 浏览器的默认安装路径
ChromiumOptions().set_browser_path(r'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome').save()浏览器路径获取方法:在浏览器地址栏输入
chrome://version或edge://version,复制"可执行文件"路径。
方法二:命令行设置
dp -p 你的浏览器路径
dp -p "C:\Program Files\Google\Chrome\Application\chrome.exe"1.5 第一个自动化脚本 #
示例:自动打开百度并搜索关键词
# 导入 DrissionPage 的 ChromiumPage 类,用于控制浏览器
from DrissionPage import ChromiumPage
# 创建 ChromiumPage 页面对象实例
page = ChromiumPage()
# 使用 get 方法打开百度首页
page.get('https://www.baidu.com')
# 使用 CSS 选择器定位搜索框元素,并输入搜索关键词 'AIAgent'
page.ele('#kw').input('AIAgent')
# 使用属性选择器定位搜索按钮元素,并执行点击操作
page.ele('@value=百度一下').click()代码说明:
ChromiumPage()创建浏览器页面对象get(url)访问指定网址ele(selector)用简洁的选择器定位元素input(text)向输入框输入内容click()点击按钮
1.6 常见问题与排查 #
- 浏览器无法启动:请检查浏览器路径设置是否正确,或尝试关闭所有已打开的 Chrome/Edge 后重试。
- Python 版本不兼容:请确保 Python 版本 ≥ 3.6。
- 依赖未安装:请确保已正确执行
pip install DrissionPage。
本章小结:
本章带你完成了 DrissionPage 的环境搭建、核心对象导入、浏览器路径设置,并通过一个完整案例体验了自动化脚本的编写。你已经可以用 DrissionPage 控制浏览器完成简单的网页操作了!
2.元素查找与选择器语法 #
2.1 元素查找概述 #
在网页自动化中,定位元素是最基础也是最重要的技能。DrissionPage 提供了一套简洁、强大且兼容性极高的元素查找语法,极大简化了代码编写和维护难度。
为什么不用浏览器右键复制路径?
- 路径冗长、可读性差
- 页面结构稍变就失效
- 不能灵活相对定位
- 不能跨 iframe 查找
DrissionPage 的优势:
- 语法简洁,易读易写
- 支持链式查找、内置等待
- 兼容 CSS Selector、XPath、Selenium 定位元组
2.2 元素查找的基本用法 #
所有页面对象和元素对象(包括 <iframe> 和 shadow-root),都可以在自己内部查找元素。
常用方法:
ele():查找单个元素eles():查找一组元素
示例页面结构:
https://static.docs-hub.com/ysczdjbyf_1750214922342.html
<div id="one">
<p class="p_cls" name="row1">第一行</p>
<p class="p_cls" name="row2">第二行</p>
<p class="p_cls">第三行</p>
</div>
<div id="two">
第二个div
</div>查找示例:
# 导入 DrissionPage 的 ChromiumPage 类,用于控制浏览器
from DrissionPage import ChromiumPage
# 创建 ChromiumPage 页面对象实例
page = ChromiumPage()
# 使用 get 方法打开指定的HTML页面
page.get('https://static.docs-hub.com/ysczdjbyf_1750214922342.html')
# 使用CSS选择器查找id为one的div元素
div1 = page.ele('#one') # id为one的div
print(div1)
# 使用属性选择器查找name属性为row1的p元素
p1 = page.ele('@name=row1') # name属性为row1的p
print(p1)
# 使用文本内容查找包含"第二个div"文本的div元素
div2 = page.ele('第二个div') # 包含文本"第二个div"的div
print(div2)
# 使用标签选择器查找所有div元素
div_list = page.eles('tag:div') # 所有div元素
print(div_list)
# 重新获取id为one的div元素
div1 = page.ele('#one')
print(div1)
# 在div1元素内部查找所有p标签元素
p_list = div1.eles('tag:p') # 在div1内查找所有p元素
print(p_list)
# 获取div1元素后面的下一个兄弟元素
div2 = div1.next() # 获取div1后面的div
print(div2)
2.3 DrissionPage 独有的选择器语法 #
2.3.1 单属性匹配 #
@属性名=值:精确匹配@属性名:值:模糊匹配(包含)@属性名^值:开头匹配@属性名$值:结尾匹配
示例:
# 导入 DrissionPage 的 ChromiumPage 类,用于控制浏览器
from DrissionPage import ChromiumPage
# 创建 ChromiumPage 页面对象实例
page = ChromiumPage()
# 使用 get 方法打开指定的HTML页面
page.get('https://static.docs-hub.com/ysczdjbyf_1750214922342.html')
# 使用精确匹配查找id为one的元素
print(page.ele('@id=one'))
# 使用模糊匹配查找class包含p_cls的元素
print(page.ele('@class:p_cls'))
# 使用开头匹配查找name以row开头的元素
print(page.ele('@name^row'))
# 使用结尾匹配查找name以row2结尾的元素
print(page.ele('@name$row2'))2.3.2 常用简写 #
#id值:id 匹配(如#one).class值:class 匹配(如.p_cls)文本内容:模糊匹配文本(如ele('第二个div'))
示例:
# 导入 DrissionPage 的 ChromiumPage 类,用于控制浏览器
from DrissionPage import ChromiumPage
# 创建 ChromiumPage 页面对象实例
page = ChromiumPage()
# 使用 get 方法打开指定的HTML页面
page.get('https://static.docs-hub.com/ysczdjbyf_1750214922342.html')
print(page.ele('#one')) # id为one
print(page.ele('.p_cls')) # class为p_cls
print(page.ele('第二个div')) # 包含文本"第二个div"2.3.3 多属性与/或/非 #
@@属性=值:多个属性"与"关系@|属性=值:多个属性"或"关系@!属性=值:否定条件
示例:
# 导入 DrissionPage 库中的 ChromiumPage 类,这个类用于控制浏览器操作
from DrissionPage import ChromiumPage
# 创建一个 ChromiumPage 页面对象实例,用于后续的网页操作
page = ChromiumPage()
# 使用 get 方法打开指定的HTML页面,访问目标网址
page.get('https://static.docs-hub.com/ysczdjbyf_1750214922342.html')
# 查找并打印class属性为p_cls且文本内容为"第三行"的元素
print(page.ele('@@class=p_cls@@text()=第三行'))
# 查找并打印name属性为row1或row2的所有元素
print(page.eles('@|name=row1@|name=row2'))
# 查找并打印没有class属性的元素
print(page.ele('@!class'))2.4 实战案例 #
案例:获取 Gitee 推荐项目标题
# 导入 DrissionPage 库中的 SessionPage 类,用于发送 HTTP 请求
from DrissionPage import SessionPage
# 创建 SessionPage 页面对象实例,用于后续的网络请求操作
page = SessionPage()
# 使用 get 方法访问 Gitee 探索页面
page.get('https://gitee.com/explore')
# 获取包含"推荐项目"文本的 div 元素
div_ele = page.ele('tag:div@class:explore-repo__list')
# 获取该 div 元素下所有 a 元素
titles = div_ele.eles('tag:a@class:title project-namespace-path')
# 打印所有标题
for i in titles:
print(i.text)2.5 兼容 CSS Selector、XPath #
DrissionPage 也支持原生 CSS Selector 和 XPath,适合复杂场景。
CSS Selector 示例: XPath 示例:
# 导入 DrissionPage 库中的 SessionPage 类,用于发送 HTTP 请求
from DrissionPage import SessionPage
# 创建 SessionPage 页面对象实例,用于后续的网络请求操作
page = SessionPage()
# 使用 get 方法访问指定的HTML页面
page.get('https://static.docs-hub.com/ysczdjbyf_1750214922342.html')
# 使用CSS选择器查找id为one的div元素下的class为p_cls的p元素
print(page.ele('css:div#one > p.p_cls'))
# 使用XPath选择器查找id为one的div元素下的class为p_cls的p元素
print(page.ele('xpath://div[@id=\"one\"]/p[@class=\"p_cls\"]'))3.元素操作与实用场景 #
3.1 元素的基本操作 #
DrissionPage 支持对网页元素进行丰富的操作,常用操作包括:
- 点击元素:
click() - 输入文本:
input(text) - 获取文本:
text属性 - 获取/设置属性:
attr('属性名')、set.attr('属性名', '值') - 获取 HTML:
html属性 - 执行 JS 脚本:
run_js('js代码')
示例:自动登录表单
# 从 DrissionPage 库中导入 ChromiumPage 类,用于控制浏览器进行自动化操作
from DrissionPage import ChromiumPage
# 创建 ChromiumPage 页面对象实例,用于后续的浏览器控制操作
page = ChromiumPage()
# 使用 get 方法访问指定的 Gitee 登录页面
page.get('https://gitee.com/login')
# 使用 CSS 选择器定位用户名输入框,并输入用户名
page.ele('#user_login').input('username')
# 使用 CSS 选择器定位密码输入框,并输入密码
page.ele('#user_password').input('password')
# 使用属性选择器定位登录按钮,并执行点击操作
page.ele('@name=commit').click()3.2 相对定位与链式操作 #
DrissionPage 支持以某个元素为基准,查找其父、子、兄弟、前后等相对位置的元素。
parent():获取父元素child()/children():获取直接子节点next()/prev():获取前后同级节点after()/before():获取文档流中前后节点
示例:
# 获取id为one的div的第一个p元素的下一个兄弟元素
div1 = page.ele('#one')
p1 = div1.ele('tag:p')
p2 = p1.next()
print(p2.text)3.3 批量操作与筛选 #
通过 eles() 获取元素列表后,可以批量操作或筛选:
- 遍历元素列表
- 使用
filter系列方法筛选(如filter.displayed()、filter.text()等) - 获取所有元素的文本、属性等集合(如
get.texts()、get.attrs('href'))
示例:批量获取所有链接文本
links = page.eles('tag:a')
for link in links:
print(link.text, link.attr('href'))
# 获取所有链接文本组成的列表
print(links.get.texts())3.4 等待元素与异常处理 #
等待元素加载 #
所有查找元素操作都自带等待机制(默认10秒),可通过 timeout 参数单独设置。
示例:
# 等待元素出现,最多等待5秒
ele = page.ele('#some_id', timeout=5)找不到元素的处理 #
- 默认找不到元素时返回
NoneElement,可用if ele:判断 - 也可全局设置找不到元素时抛出异常
示例:
ele = page.ele('#not_exist')
if not ele:
print('元素未找到')
# 全局设置找不到元素时抛出异常
from DrissionPage.common import Settings
Settings.raise_when_ele_not_found = True3.5 实用场景案例 #
<body>
<form id="hobbyForm">
<label><input type="checkbox" name="hobby" value="reading"> 阅读</label>
<label><input type="checkbox" name="hobby" value="music"> 音乐</label>
<label><input type="checkbox" name="hobby" value="sports"> 运动</label>
</form>
<select id="citySelect">
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="guangzhou">广州</option>
</select>
<ul id="itemList">
<li>苹果</li>
<li>香蕉</li>
<li>橙子</li>
</ul>
</body># 从DrissionPage库中导入ChromiumPage类,用于控制浏览器进行自动化操作
from DrissionPage import ChromiumPage
# 创建ChromiumPage页面对象实例,用于后续的浏览器控制操作
page = ChromiumPage()
# 使用get方法访问指定的网页地址
page.get('https://static.docs-hub.com/7_1750227952921.html') # 替换为实际页面
# 查找页面上所有的复选框元素
checkboxes = page.eles('tag:input@type=checkbox')
print(checkboxes)
# 遍历所有复选框元素
for cb in checkboxes:
# 检查复选框是否未被选中
if not cb.states.is_checked:
# 如果未选中,则点击该复选框
cb.click()
# 查找页面上的select下拉框元素
select = page.ele('tag:select')
# 获取select元素下的所有option选项元素
options = select.eles('tag:option')
# 遍历所有选项元素
for opt in options:
# 检查选项的文本是否为"上海"
if opt.text == '上海':
# 如果找到"上海"选项,则点击选择它
opt.click()
# 找到目标选项后跳出循环
break
# 主动等待所有li列表项元素加载完成
page.wait.eles_loaded('tag:li')
# 获取页面上所有的li列表项元素
items = page.eles('tag:li')
# 遍历所有列表项元素
for item in items:
# 打印每个列表项的文本内容
print(item.text)4.进阶用法与实战项目 #
4.1 多页面与多标签管理 #
在实际开发中,经常需要同时操作多个页面或标签。DrissionPage 支持多标签、多窗口的灵活管理。
常用操作:
- 新建标签页:
page.new_tab() - 获取所有标签页:
page.get_tabs() - 切换标签页:
page.activate_tab(标签页 id) - 关闭标签页:
page.close_tabs() - 切换标签页
示例:在新标签页中打开163并切换回原标签
# 导入DrissionPage库中的ChromiumPage类,用于控制浏览器
from DrissionPage import ChromiumPage
# 导入time模块,用于实现延时等待
import time
# 创建ChromiumPage页面对象实例
page = ChromiumPage()
# 在新标签页中打开百度首页,并返回该标签页对象
tab2 = page.new_tab('https://www.baidu.com')
# 等待1秒,确保页面加载完成
time.sleep(1)
# 在新标签页中打开网易首页,并返回该标签页对象
tab3 = page.new_tab('https://www.163.com')
# 再等待1秒,确保页面加载完成
time.sleep(1)
# 激活(切换到)tab2标签页(即百度页面)
page.activate_tab(tab2.tab_id)
# 再等待1秒,确保切换完成
time.sleep(1)
# 打印当前激活标签页的标题
print(page.title)4.2 实战项目:自动化批量下载图片 #
需求:
自动访问一个图片列表页面,批量下载所有图片到本地。
HTML 示例:
<div class="img-list">
<img src="https://static.docs-hub.com/baidu_1750232267155.png">
<img src="https://static.docs-hub.com/sougou_1750232276797.png">
</div>Python 实现:
# 从DrissionPage库导入ChromiumPage类
from DrissionPage import ChromiumPage
# 导入os和requests模块
import os, requests
# 创建一个ChromiumPage对象,用于操作浏览器页面
page = ChromiumPage()
# 打开指定的网页
page.get('https://static.docs-hub.com/8_1750232305740.html')
# 获取页面中所有img标签的元素
imgs = page.eles('tag:img')
# 创建一个名为imgs的文件夹,如果已存在则不报错
os.makedirs('imgs', exist_ok=True)
# 遍历所有图片元素
for img in imgs:
# 获取图片的src属性,即图片的URL
url = img.attr('src')
# 生成图片的保存路径,保存在imgs文件夹下,文件名为图片URL的最后一部分
filename = os.path.join('imgs', os.path.basename(url))
# 发送HTTP请求,下载图片内容
resp = requests.get(url)
# 以二进制写入方式打开文件,准备保存图片
with open(filename, 'wb') as f:
# 将下载的图片内容写入文件
f.write(resp.content)
# 打印已下载图片的文件名
print(f'已下载: {filename}')