DrissionPage

DrissionPagae
DrissionPage:类似 selenuium 的网页自动化工具。这是一个基于 Python 的网页自动化工具,支持 Chromium 内核浏览器。它将控制浏览器和收发请求两大功能合二为一,并提供了统一、简洁的接口。

环境
操作系统:Windows、Linux 或 Mac。
python 版本:3.6 及以上
支持应用:Chromium 内核浏览器(如 Chrome、Edge),electron 应用

相关
github - DrissionPage

文档 - DrissionPage
DrissionPageJava: DrissionPage的Jave版本
SaossionPage: Drissionpage 库的兄弟版 SaossionPage 简称骚神

元素定位助手 和 代码生成助手: https://gitee.com/haiyang0726/SaossionPage/releases
DataRecorder
数据写入

优势
无 webdriver 特征
无需为不同版本的浏览器下载不同的驱动
运行速度更快
可以跨<iframe>查找元素,无需切入切出
把<iframe>看作普通元素,获取后可直接在其中查找元素,逻辑更清晰
可以同时操作浏览器中的多个标签页,即使标签页为非激活状态,无需切换
可以直接读取浏览器缓存来保存图片,无需用 GUI 点击另存
可以对整个网页截图,包括视口外的部分(90以上版本浏览器支持)
可处理非open状态的 shadow-root
支持应用:Chromium 内核浏览器(如 Chrome、Edge),electron 应用
可能之所以不被检测到,是因为DrissionPage的底层基于cdp协议(Chrome DevTools Protocol)),
以下是懒神推荐读的cdp代码  https://chromedevtools.github.io/devtools-protocol/
什么是cdp
众所周知F12能够打开开发者工具Q进行调试,开发者工具即DevTools大家应该都知道,那么ChromeDevTools就是用的CDP协议来跟浏览器进行交互的调试等一系列操作的。CDP是通过RESTfulAPI提供了对浏览器内部运行情况的访问,可以通过这些API来控制Chrome浏览器的行为,来做到与DevTools类似的功能:获取页面信息、监控网络活动、执行JS等操作。cdp协议简称chrome调试协议,是基于scoket(websocketQ、usb、adb)消息的jsonrpc协议。用来调用chrome内部的方法实现js,css,dom的开发调试。可以将实现了cdp协议的应用看做rpc调用的服务端(chrome,puppeteer),将调试面板看做rpc调用的客户端(devtools)。

pip install DrissionPage

#更新较快,快进行更新
pip install DrissionPage --upgrade 
1
2
3
4
默认配置
默认配置在这里

D:\ruanjian\PY\Miniconda3\Lib\site-packages\DrissionPage\_configs\config.ini
1
[paths]
download_path =
tmp_path =

[chromium_options]
address = 127.0.0.1:9222
browser_path = chrome
arguments = ['--no-default-browser-check', '--disable-suggestions-ui', '--no-first-run', '--disable-infobars', '--disable-popup-blocking', '--hide-crash-restore-bubble', '--disable-features=PrivacySandboxSettings4']
extensions = []
prefs = {'profile.default_content_settings.popups': 0, 'profile.default_content_setting_values': {'notifications': 2}}
flags = {}
load_mode = normal
user = Default
auto_port = False
system_user_path = False
existing_only = False

[session_options]
headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8', 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'connection': 'keep-alive', 'accept-charset': 'GB2312,utf-8;q=0.7,*;q=0.7'}

[timeouts]
base = 10
page_load = 30
script = 30

[proxies]
http =
https = 

[others]
retry_times = 3
retry_interval = 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
SessionPage
SessionPage对象和WebPage对象的 s 模式,可用收发数据包的形式访问网页。

顾名思义,SessionPage是一个使用使用Session(requests 库)对象的页面,它使用 POM 模式封装了网络连接和 html 解析功能,使收发数据包也可以像操作页面一样便利。

并且,由于加入了本库独创的查找元素方法,使数据的采集便利性远超 requests + beautifulsoup 等组合。

创建页面对象
通过配置信息创建
如果需要在使用前进行一些配置,可使用SessionOptions。它是专门用于设置Session对象初始状态的类,内置了常用的配置。详细使用方法见“启动配置”一节。

从指定 ini 文件创建
以上方法是使用默认 ini 文件中保存的配置信息创建对象,你可以保存一个 ini 文件到别的地方,并在创建对象时指定使用它。

from DrissionPage import SessionPage, SessionOptions

# 创建配置对象时指定要读取的ini文件路径
so = SessionOptions(ini_path=r'./config1.ini')
# 使用该配置对象创建页面
page = SessionPage(session_or_options=so)
1
2
3
4
5
6
不使用 ini 文件
可以用以下方法,指定不使用 ini 文件的配置,而把配置写在代码中。

from DrissionPage import SessionPage, SessionOptions

so = SessionOptions(read_file=False)  # read_file设为False
so.set_retry(5)
page = SessionPage(so)
1
2
3
4
5
传递控制权
当需要使用多个页面对象共同操作一个页面时,可在页面对象创建时接收另一个页面间对象传递过来的Session对象,以达到多个页面对象同时使用一个Session对象的效果。

# 创建一个页面
page1 = SessionPage()
# 获取页面对象内置的Session对象
session = page1.session
# 在第二个页面对象初始化时传递该对象
page2 = SessionPage(session_or_options=session)
1
2
3
4
5
6
访问
get
get()方法语法与 requests 的get()方法一致,在此基础上增加了连接失败重试功能。与 requests 不一样的是,它不返回Response对象。

参数名称    类型    默认值    说明
url    str    必填    目标 url
show_errmsg    bool    False    连接出错时是否显示和抛出异常
retry    int    None    重试次数,为None时使用页面参数,默认 3
interval    float    None    重试间隔(秒),为None时使用页面参数,默认 2
timeout    float    None    加载超时时间(秒)
**kwargs    -    None    连接所需其它参数,具体见 requests 用法
读取本地文件
get()的url参数可指向本地文件,实现本地 html 解析。

from DrissionPage import SessionPage

page = SessionPage()
page.get(r'D:\demo.html')
1
2
3
4
访问在线网页

from DrissionPage import SessionPage

page = SessionPage()

url = 'https://www.baidu.com'
headers = {'referer': 'gitee.com'}
cookies = {'name': 'value'}
proxies = {'http': '127.0.0.1:1080', 'https': '127.0.0.1:1080'}
page.get(url, headers=headers, cookies=cookies, proxies=proxies)
1
2
3
4
5
6
7
8
9
post
post 方式请求页面。用法与get()一致。返回bool

# 向 data 参数传入字符串
page.post(url, data='abc=123')

# 向 data 参数传入字典
page.post(url, data={'abc': '123'})

# 向 json 参数传入字符串
page.post(url, json='abc=123')

# 向 json 参数传入字典
page.post(url, json={'abc': '123'})


page.json()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ChromiumPage
ChromiumPage对象和WebPage对象的 d 模式,可操控浏览器。本章介绍ChromiumPage。

顾名思义,ChromiumPage是 Chromium 内核浏览器的页面,它用 POM 方式封装了操控网页所需的属性和方法。

使用它,我们可与网页进行交互,如调整窗口大小、滚动页面、操作弹出框等等。

通过从中获取的元素对象,我们还可以跟页面中的元素进行交互,如输入文字、点击按钮、选择下拉菜单等等。

甚至,我们可以在页面或元素上运行 JavaScript 代码、修改元素属性、增删元素等。

除了与页面和元素的交互,ChromiumPage还扮演着浏览器控制器的角色,可以说,一个ChromiumPage对象,就是一个浏览器。

它可以对标签页进行管理,可以对下载任务进行控制。可以为每个标签页生成独立的页面对象(ChromiumTab),以实现多标签页同时操作,而无需切入切出。

ChromiumPage()参数
addr_or_opts: 浏览器地址:端口、ChromiumOptions对象或端口数字(int)
tab_id: 要控制的标签页id,不指定默认为激活的
timeout: 超时时间(秒)
启动或接管浏览器
会使用默认配置,自动生成页面对象
只要这个浏览器不关闭,下次运行程序时会接管同一个浏览器继续操作(配置的 ip: port 信息不变)。这种方式极大地方便了程序的调试,使程序不必每次重新开始,可以单独调试某个功能。

from DrissionPage import ChromiumPage

# 创建对象同时启动浏览器,如果浏览器已经存在,则接管它
page = ChromiumPage()  
1
2
3
4
接管已打开的浏览器
页面对象创建时,只要指定的地址(ip: port)已有浏览器在运行,就会直接接管。无论浏览器是下面哪种方式启动的。

多浏览器共存(推荐)
如果想要同时操作多个浏览器,或者自己在使用其中一个上网,同时控制另外几个跑自动化,就需要给这些被程序控制的浏览器设置单独的端口和用户文件夹,否则会造成冲突。

from DrissionPage import ChromiumPage, ChromiumOptions

co = ChromiumOptions().set_paths(local_port=9999, user_data_path='./user_data')
page = ChromiumPage(addr_or_opts=co)
page.get('https://www.baidu.com')
1
2
3
4
5
ChromiumOptions对象的auto_port()方法,可以指定程序每次使用空闲的端口和临时用户文件夹创建浏览器。也是每个浏览器要使用独立的ChromiumOptions对象。但这种方法创建的浏览器不能重复使用。

# 初始化Chromium浏览器选项
co = ChromiumOptions().auto_port()
# 创建Chromium页面对象
page = ChromiumPage(co)
1
2
3
4
使用系统浏览器用户目录
这种情况下用户不能打开一个浏览器使用
初始默认配置下,程序会为每个使用的端口创建空的用户目录,并且每次接管都使用,这样可以有效避免浏览器冲突。

有些时候我们希望使用系统安装的浏览器的默认用户文件夹。以便复用用户信息和插件等。

from DrissionPage import ChromiumPage, ChromiumOptions

co = ChromiumOptions().use_system_user_path()
page = ChromiumPage(co)
1
2
3
4
使用 ini 文件
把这个配置记录到 ini 文件,就不用每次使用都配置。

from DrissionPage import ChromiumOptions

ChromiumOptions().use_system_user_path().save()
1
2
3
ChromiumOptions对象
命令行参数设置
ChromiumOptions对象下的方法

[!NOTE] set_argument():用于设置启动参数。

arg [str] 必填 启动参数名称
value[str|None|False]=None 参数的值。带值的参数传入属性值,没有值的传入None。如传入False,删除该参数。
[!NOTE] remove_argument()
Contents

[!NOTE] clear_arguments()
Contents

# 设置启动时最大化
co.set_argument('--start-maximized')
# 设置初始窗口大小
co.set_argument('--window-size', '800,600')
# 使用来宾模式打开浏览器
co.set_argument('--guest')


#禁用通知警告
co.set_argument('--disable-notifications')

#禁止所有弹出窗口
co.set_pref(arg='profile.default_content_settings.popups', value='0')

#阻止“自动保存密码”的提示气泡
co.set_pref('credentials_enable_service', False)

#阻止“要恢复页面吗?Chrome未正确关闭”的提示气泡
co.set_argument('--hide-crash-restore-bubble')

#通知用户他们的浏览器是由自动测试控制的。
co.set_argument('--enable-automation')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
运行路径及端口
📌 set_browser_path()
📌 set_tmp_path()
📌 set_local_port()
📌 set_address()
📌 auto_port()
📌 set_user_data_path()
📌 use_system_user_path()
📌 set_cache_path()
📌 existing_only()
使用插件
📌 add_extension()
📌 remove_extensions()

方法
参数

ChromiumOptions()
read_file=True,
ini_path=None
方法
ChromiumOptions()对象.方法名
运行参数设置

set_timeouts(base,page_load,script):用于设置几种超时时间,以秒为单位

base默认超时时间,用于元素等待、alert 等待、WebPage的 s 模式连接等等,除以下两个参数的场景,都使用这个设置
page_load 页面加载超时时间
script JavaScript 运行超时时间
set_load_mode():用于设置网页加载策略。加载策略是指强制页面停止加载的时机,如加载完 DOM 即停止,不加载图片资源等,以提高自动化效率。

'normal':阻塞进程,等待所有资源下载完成(默认)
'eager':DOM 就绪即停止加载
'none':网页连接成功即停止加载
set_proxy():用于设置浏览器代理。

常用设置

set_paths():快捷的路径设置函数

browser_path: 浏览器可执行文件路径C:\Program Files\Google\Chrome\Application\chrome.exe
local_port: 本地端口号
address: 调试浏览器地址,例:127.0.0.1:9222
download_path: 下载文件路径
user_data_path: 用户数据路径
cache_path: 缓存路径
一般来说用户文件夹的名称是 User Data。对于默认情况下的 Windows 中的 Chrome 浏览器来说,此文件夹位于 %USERPROFILE%\AppData\Local\Google\Chrome\User Data\

实际路径请在浏览器输入 chrome://version/,查阅其中的个人资料路径或者叫用户配置路径。

📌 set_tmp_path():用于设置临时文件存放路径。

📌 auto_port():设置是否使用自动分配的端口,启动一个全新的浏览器。

如果设置为True,程序会自动寻找一个可用端口,并在指定路径或系统临时文件夹创建一个文件夹,用于储存浏览器数据。
由于端口和用户文件夹都是唯一的,所以用这种方式启动的浏览器不会产生冲突,但也无法多次启动程序时重复接管同一个浏览器。
set_local_port()、set_address()和set_user_data_path()方法,会和auto_port()互相覆盖,即以后调用的为准。
📌 set_user_data_path()此方法用于设置用户文件夹路径。用户文件夹用于存储当前登陆浏览器的账号在使用浏览器时留下的痕迹,包括设置选项等。

📌 use_system_user_path():设置是否使用系统安装的浏览器默认用户文件夹

📌 existing_only():设置是否仅使用已启动的浏览器,如连接目标浏览器失败,会抛出异常,不会启动新浏览器。

on_off bool True bool表示开关
属性
📌 address为要控制的浏览器地址,格式为 ip:port,默认为’127.0.0.0:9222’。类型:str
📌 browser_path:该属性返回浏览器可执行文件的路径。类型:str
📌 user_data_path
该属性返回用户数据文件夹路径。
类型:str
📌 tmp_path:该属性返回临时文件夹路径,可用于保存自动分配的用户文件夹路径。类型:str
📌 download_path
该属性返回默认下载路径文件路径。
类型:str
📌 user:该属性返回用户配置文件夹名称。类型:str
📌 load_mode该属性返回页面加载策略。有’normal’、‘eager’、'none’三种 ,类型:str
📌 timeouts:该属性返回超时设置。包括三种:‘base’、‘page_load’、‘script’。类型:dict
print(co.timeouts)
输出:

{
    'base': 10,
    'page_load': 30,
    'script': 30
}
1
2
3
4
5
📌 retry_times该属性返回连接失败时的重试次数。类型:int
📌 retry_interval该属性返回连接失败时的重试间隔(秒)。类型:float
📌 proxy该属性返回代理设置。类型:str
📌 arguments该属性以list形式返回浏览器启动参数。类型:list
📌 extensions该属性以list形式返回要加载的插件路径。类型:list
📌 preferences该属性返回用户首选项配置。类型:dict
📌 system_user_path该属性返回是否使用系统按照的浏览器的用户文件夹。类型:bool
📌 is_existing_only该属性返回是否仅使用已打开的浏览器。类型:bool
📌 is_auto_port:该属性返回是否仅使用自动分配端口和用户文件夹路径。类型:bool

访问网页
ChromiumPage对象和WebPage对象的 d 模式都能控制浏览器访问网页。这里只对ChromiumPage进行说明

get():用于跳转到一个网址。当连接失败时,程序会进行重试。
参数名称    类型    默认值    说明
url    str    必填    目标 url,可指向本地文件路径
show_errmsg    bool    False    连接出错时是否显示和抛出异常
retry    int    None    重试次数,为None时使用页面参数,默认 3
interval    float    None    重试间隔(秒),为None时使用页面参数,默认 2
timeout    float    None    加载超时时间(秒)
加载模式
加载模式是指程序在页面加载阶段的行为模式,有以下三种:

normal():常规模式,会等待页面加载完毕,超时自动重试或停止,默认使用此模式

eager():加载完 DOM 或超时即停止加载,不加载页面资源

none():超时也不会自动停止,除非加载完成

前两种模式下,页面加载过程会阻塞程序,直到加载完毕才执行后面的操作。

none()模式下,只在连接阶段阻塞程序,加载阶段可自行根据情况执行stop_loading()停止加载。

这样提供给用户非常大的自由度,可等到关键数据包或元素出现就主动停止页面加载,大幅提升执行效率。

加载完成是指主文档完成,并不包括由 js 触发的加载和重定向的加载。 当文档加载完成,程序就判断加载完毕,此后发生的重定向或 js 加载数据需用其它逻辑处理。

配置对象中设置

from DrissionPage import ChromiumOptions, ChromiumPage
co = ChromiumOptions().set_load_mode('none')
page = ChromiumPage(co)
1
2
3
运行中设置

from DrissionPage import ChromiumPage
page = ChromiumPage()
page.set.load_mode.none()
1
2
3
none模式技巧
示例 1,配合监听器

跟监听器配合,可在获取到需要的数据包时,主动停止加载。

from DrissionPage import ChromiumPage

page = ChromiumPage()
page.set.load_mode.none()  # 设置加载模式为none

page.listen.start('api/getkeydata')  # 指定监听目标并启动监听
page.get('http://www.hao123.com/')  # 访问网站
packet = page.listen.wait()  # 等待数据包
page.stop_loading()  # 主动停止加载
print(packet.response.body)  # 打印数据包正文
1
2
3
4
5
6
7
8
9
10
示例 2,配合元素查找

跟元素查找配合,可在获取到某个指定元素时,主动停止加载。

from DrissionPage import ChromiumPage

page = ChromiumPage()
page.set.load_mode.none()  # 设置加载模式为none

page.get('http://www.hao123.com/')  # 访问网站
ele = page.ele('中国日报')  # 查找text包含“中国日报”的元素
page.stop_loading()  # 主动停止加载
print(ele.text)  # 打印元素text
1
2
3
4
5
6
7
8
9
示例 2,配合页面特征

可等待到页面到达某种状态时,主动停止加载。比如多级跳转的登录,可等待 title 变化到最终目标网址时停止。

from DrissionPage import ChromiumPage

page = ChromiumPage()
page.set.load_mode.none()  # 设置加载模式为none

page.get('http://www.hao123.com/')  # 访问网站
page.wait.title_change('hao123')  # 等待title变化出现目标文本
page.stop_loading()  # 主动停止加载
1
2
3
4
5
6
7
8
获取网页信息
成功访问网页后,可使用ChromiumPage自身属性和方法获取页面信息。

操控浏览器除了ChromiumPage,还有ChromiumTab和ChromiumFrame两种页面对象分别对应于标签页对象和<iframe>元素对象,后面会有单独章节介绍。

页面信息
📌 html:返回当前页面 html 文本。
📌 json:把请求内容解析成 json。
📌 title:返回当前页面title文本。
📌 user_agent:返回当前页面 user agent 信息。
📌 browser_version:返回当前浏览器版本号。
📌 save():把当前页面保存为文件,同时返回保存的内容。

参数名称    类型    默认值    说明
path    str
Path    None    保存路径,为None且name不为None时保存到当前路径
name    str    None    保存的文件名,为None且path不为None时使用 title 值
as_pdf    bool    False    为Ture保存为 pdf,否则保存为 mhtml 且忽略kwargs参数
**kwargs    多种    无    pdf 生成参数
运行状态信息
📌 url:返回当前访问的 url。
📌 address:返回当前对象控制的页面地址和端口。
📌 tab_id:返回当前标签页的 id。
📌 process_id:返回浏览器进程 id。
📌 states.is_loading:返回页面是否正在加载状态。
📌 states.is_alive:返回页面是否仍然可用,标签页已关闭则返回False。

📌 states.ready_state:返回页面当前加载状态,有 4 种:
‘connecting’: 网页连接中
'loading':表示文档还在加载中
'interactive':DOM 已加载,但资源未加载完成
'complete':所有内容已完成加载
📌 url_available:以布尔值返回当前链接是否可用。
📌 states.has_alert:以布尔值返回页面是否存在弹出框。
窗口信息
📌 rect.size:以tuple返回页面大小,格式:(宽, 高)。
📌 rect.window_size:以tuple返回窗口大小,格式:(宽, 高)。
📌 rect.window_location:以tuple返回窗口在屏幕上的坐标,左上角为(0, 0)。
📌 rect.window_state:以返回窗口当前状态,有'normal'、'fullscreen'、'maximized'、 'minimized'几种。
📌 rect.viewport_size:以tuple返回视口大小,不含滚动条,格式:(宽, 高)。
📌 rect.viewport_size_with_scrollbar:以tuple返回浏览器窗口大小,含滚动条,格式:(宽, 高)。
📌 rect.page_location:以tuple返回页面左上角在屏幕中坐标,左上角为(0, 0)。
📌 rect.viewport_location:以tuple返回视口在屏幕中坐标,左上角为(0, 0)。
配置参数信息
📌 timeout
📌 timeouts
📌 retry_times
📌 retry_interval
📌 load_mode

cookies 和缓存信息
📌 cookies():返回 cookies 信息。
📌 session_storage():用于获取 sessionStorage 信息,可获取全部或单个项。
📌 local_storage():用于获取 localStorage 信息,可获取全部或单个项。

内嵌对象
📌 driver:返回当前页面对象使用的Driver对象。

自动等待
页面对象的等待
wait.load_start():等待页面进入加载状态后。
wait.doc_loaded()
wait.ele_loaded()
wait.ele_displayed()
wait.ele_hidden()
wait.ele_deleted()
wait.download_begin()
wait.upload_paths_inputted()
wait.new_tab()
wait.title_change()
wait.url_change()
wait()

标签页操作
一个 Tab 对象(ChromiumTab和WebPageTab)控制一个浏览器的标签页,是页面控制的主要单位。

一个标签页也可以被多个 Tab 对象同时控制(需禁用单例)。

DrissionPage 支持多 tab 对象共存,对象之间互不影响,而且标签页无需激活即可操作。

多标签页用法
标签页总览
📌 tabs_count
📌 tab_ids

新建标签页
new_tab()
参数名称    类型    默认值    说明
url    str
None    None    新标签页访问的网址,不传入则新建空标签页
new_window    bool    False    是否在新窗口打开标签页
background    bool    False    是否不激活新标签页,如new_window为True则无效
new_context    bool    False    是否创建新的上下文,为True则打开一个无痕模式的新窗口,新窗口与其它窗口不共用 cookies
wait.new_tab():用于等待新标签页出现。
timeout 超时时间,为None时使用页面timeout设置
raise_err 等待失败时是否报错,为None时根据Settings设置
等待成返回新标签页 id,等待失败返回False
获取标签页对象
📌 get_tab():获取一个标签页对象。可指定标签页序号、id、标题、url、类型等条件用于检索。
📌 get_tabs():查找符合条件的 tab 对象。可指定标签页标题、url、类型等条件用于检索。
title str 要匹配的标题文本,模糊匹配,为None则匹配所有
url str 要匹配的 url 文本,模糊匹配,为None则匹配所有
tab_type 标签页类型,可用列表输入多个,如’page’,'iframe’等,
as_id bool 是否返回标签页 id 而不是标签页对象
📌 latest_tab:返回最后激活的标签页对象。指最新出现或最新被激活的标签页。
tab = page.get_tab()  # 获取Page对象控制的标签页的Tab对象(即Page和Tab对象同时控制一个标签页)
tab = page.get_tab(1)  # 获取列表中第1个标签页的对象
tab = page.get_tab('5399F4ADFE3A27503FFAA56390344EE5')  # 获取列表中指定id标签页的对象
tab = page.get_tab(url='baidu.com')  # 获取所有url中带 'baidu.com' 的标签页对象
1
2
3
4
from DrissionPage import ChromiumPage

page = ChromiumPage()
page.get('https://www.baidu.com')
page.new_tab('https://www.baidu.com')

tabs = page.get_tabs(url='baidu.com')
print(tabs)
1
2
3
4
5
6
7
8
# 打开了一个标签页
ele.click()
# 获取最新标签页对象
tab = page.latest_tab  # 与page.get_tab(0)效果一致
1
2
3
4
使用多例
默认情况下,Tab 对象是单例的,即一个标签页只有一个对象,即使重复使用get_tab(),获取的都是同一个对象。

这主要是防止新手不理解机制,反复创建多个连接导致资源耗费。

实际上允许多个 Tab 对象同时操作一个标签页,每个负责不同的工作。比如一个执行主逻辑流程,另外的监视页面,处理各种弹窗。

要允许多例,可用Settings设置:

from DrissionPage.common import Settings

Settings.singleton_tab_obj = False
1
2
3
from DrissionPage import ChromiumPage
from DrissionPage.common import Settings

page = ChromiumPage()
page.new_tab()
page.new_tab()

# 未启用多例:
tab1 = page.get_tab(1)
tab2 = page.get_tab(1)
print(id(tab1), id(tab2))

# 启用多例:
Settings.singleton_tab_obj = False
tab1 = page.get_tab(1)
tab2 = page.get_tab(1)
print(id(tab1), id(tab2))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
关闭和重连
📌 close():用于标签页关闭自己。Page 对象和 Tab 对象都有此方法。
📌 disconnect():用于页面对象断开和浏览器的连接,但不关闭标签页。断开后,对象不能对标签页进行操作。Page 对象和 Tab 对象都有此方法。
📌 reconnect():用于关闭与页面连接,然后重建一个新连接。这主要用于应付长期运行导致内存占用过高,断开连接可释放内存,然后重连继续控制浏览器。Page、Tab 和ChromiumFrame对象都有此方法。
📌 close_tabs():用于关闭指定的标签页,可关闭多个。默认关闭当前的。只有 Page 对象拥有。
tabs_or_ids:要处理的标签页对象或 id,可传入列表或元组,为None时处理当前页
others [bool]:是否关闭指定标签页之外的
激活标签页
📌 set.tab_to_front():此方法用于激活标签页使其处于最前面。但不会把当前对象焦点跳转到该标签页。只有 Page 对象拥有
📌 set.activate():此方法用于 Tab 对象或 Page 对象激活自己。
多标签页协同
iframe 操作
获取<iframe>对象
获取<iframe>对象的方法有两种,可用获取普通元素的方式获取,或者用get_frame()方法获取。推荐优先使用get_frame() 方法,因为当作普通元素获取时,IDE 无法正确识别获取到的是<iframe>元素。

# 使用定位符获取
iframe = page.get_frame('#sss')

# 获取第2个iframe
iframe = page.get_frame(1)
1
2
3
4
5
📌 get_frame()
📌 get_frames():获取页面中多个符合条件的<frame>或<iframe>对象。获取所有<iframe>会很慢,而且浪费资源,一般使用获取需要用到的就好。
📌 普通元素方式

查找<iframe>内元素
在<iframe>内查找

# 使用定位符获取
iframe = page.get_frame('#sss')
ele = iframe('首页')
print(ele)
#<ChromiumElement a href='https://www.runoob.com/' data-id='index' title='菜鸟教程' class='current'>
1
2
3
4
5
页面跨<iframe>查找
如果<iframe>元素的网址和主页面是同域的,我们可以直接用页面对象查找<iframe>内部元素,而无需先获取ChromiumFrame对象:

ele = page('首页')
print(ele)
#<ChromiumElement a href='https://www.runoob.com/' data-id='index' title='菜鸟教程' class='current'>
1
2
3
监听网络数据
许多网页的数据来自接口,在网站使用过程中动态加载,如使用 JS 加载内容的翻页列表。

这些数据通常以 json 形式发送,浏览器接收后,对其进行解析,再加载到 DOM 相应位置。

做数据采集的时候,我们往往从 DOM 中去获取解析后数据的,可能存在数据不全、加载响应不及时、难以判断加载完成等问题。

如果我们可以拿到浏览器收发的数据包,根据数据包状态判断下一步操作,甚至直接获取数据,岂不是爽爆了?

DrissionPage 每个页面对象(包括 Tab 和 Frame 对象)内置了一个监听器,专门用于抓取浏览器数据包。可以提供等待和捕获指定数据包,实时返回指定数据包功能。

等待并获取

from DrissionPage import ChromiumPage

page = ChromiumPage()
page.get('https://gitee.com/explore/all')  # 访问网址,这行产生的数据包不监听

page.listen.start('gitee.com/explore')  # 开始监听,指定获取包含该文本的数据包
for _ in range(5):
    page('@rel=next').click()  # 点击下一页
    res = page.listen.wait()  # 等待并获取一个数据包
    print(res.url)  # 打印数据包url
1
2
3
4
5
6
7
8
9
10
实时获取

from DrissionPage import ChromiumPage

page = ChromiumPage()
page.listen.start('gitee.com/explore')  # 开始监听,指定获取包含该文本的数据包
page.get('https://gitee.com/explore/all')  # 访问网址

i = 0
for packet in page.listen.steps():
    print(packet.url)  # 打印数据包url
    page('@rel=next').click()  # 点击下一页
    i += 1
    if i == 5:
        break
1
2
3
4
5
6
7
8
9
10
11
12
13
设置目标和启动监听
📌 listen.start():用于启动监听器,启动同时可设置获取的目标特征。可设置多个特征,符合条件的数据包会被获取。如果监听未停止时调用这个方法,可清除已抓取的队列。
📌 listen.set_targets():可在监听过程中修改监听目标,也可在监听开始前设置。如监听未启动,不会启动监听。
以上两个函数的参数一样

参数名称    类型    默认值    说明
targets    str
list
tuple
set    None    要匹配的数据包 url 特征,可用列表指定多个,为True时获取所有
is_regex    bool    None    设置的 target 是否正则表达式,为None时保持原来设置
method    str
list
tuple
set    None    设置监听的请求类型,可指定多个,默认('GET', 'POST'),为True时监听所有,为None时保持原来设置
res_type    str
list
tuple
set    None    设置监听的 ResourceType 类型,可指定多个,为True时监听所有,为None时保持原来设置
等待和获取数据包
📌 listen.wait():用于等待符合要求的数据包到达指定数量。所有符合条件的数据包都会存储到队列,wait()实际上是逐个从队列中取结果,不用担心页面已刷走而丢包。
📌 listen.steps():此方法返回一个可迭代对象,用于for循环,每次循环可从中获取到的数据包。可实现实时获取并返回数据包。如果timeout超时,会中断循环。
📌 listen.wait_silent():用于等待所有指定的请求完成。
📌 listen.wait():用于等待符合要求的数据包到达指定数量。所有符合条件的数据包都会存储到队列,wait()实际上是逐个从队列中取结果,不用担心页面已刷走而丢包。

参数名称    类型    默认值    说明
count    int    1    需要捕捉的数据包数量
timeout    float
None    None    超时时间,为None无限等待
fit_count    bool    True    是否必需满足总数要求,如超时,为True返回False,为False返回已捕捉到的数据包
raise_err    bool    None    超时时是否抛出错误,为None时根据Settings设置,如不抛出,超时返回False
返回类型    说明
DataPacket    count为1且未超时,返回一个数据包对象
List[DataPacket]    count大于1,未超时或fit_count为False,返回数据包对象组成的列表
False    超时且fit_count为True时
📌 listen.steps():此方法返回一个可迭代对象,用于for循环,每次循环可从中获取到的数据包。可实现实时获取并返回数据包。如果timeout超时,会中断循环。

参数名称    类型    默认值    说明
count    int    None    需捕获的数据包总数,为None表示无限
timeout    float
None    None    每个数据包等待时间,为None表示无限等待
gap    int    1    每接收到多少个数据包返回一次数据
返回类型    说明
DataPacket    gap为1时,返回一个数据包对象
List[DataPacket]    gap大于1,返回数据包对象组成的列表
📌 listen.wait_silent():用于等待所有指定的请求完成。

参数名称    类型    默认值    说明
timeout    float
None    None    等待时间,为None表示无限等待
targets_only    bool    False    是否只等待targets指定的请求结束
limit    int    0    剩下多少个连接时视为结束
返回类型    说明
bool    是否等待成功
暂停和恢复
📌 listen.pause(clear):用于暂停监听。
clear [bool] True 是否清空已获取队列
📌 listen.resume():此方法用于继续暂停的监听。
📌 listen.stop():此方法用于终止监听器的运行,会清空已获取的队列,不清空 targets。
DataPacket对象
DataPacket对象是获取到的数据包结果对象,包含了数据包各种信息。

对象属性

属性名称    数据类型    说明
tab_id    str    产生这个请求的标签页的 id
frameId    str    产生这个请求的框架 id
target    str    产生这个请求的监听目标
url    str    数据包请求网址
method    str    请求类型
is_failed    bool    是否连接失败
resourceType    str    资源类型
request    Request    保存请求信息的对象
response    Response    保存响应信息的对象
fail_info    FailInof    保存连接失败信息的对象
wait_extra_info()
有些数据包有extra_info数据,但这些数据可能会迟于数据包返回,用这个方法可以等待这些数据加载到数据包对象。

参数名称    类型    默认值    说明
timeout    float
None    None    超时时间,None为无限等待
返回类型    说明
bool    是否等待成功
📌 wait_extra_info()

Request对象
Request对象是DataPacket对象内用于保存请求信息的对象,有以下属性:

属性名称    数据类型    说明
url    str    请求的网址
method    str    请求类型
headers    CaseInsensitiveDict    以大小写不敏感字典返回 headers 数据
cookies    List[dict]    返回发送的 cookies
postData    str
dict    post 类型的请求所提交的数据,json 以dict格式返回
除以上常用属性,还有以下属性,自行体会:

urlFragment、hasPostData、postDataEntries、mixedContentType、initialPriority、referrerPolicy、isLinkPreload、trustTokenParams、isSameSite

Response对象
DataPacket.respose

Response对象是DataPacket对象内用于保存响应信息的对象,有以下属性:

属性名称    数据类型    说明
url    str    请求的网址
headers    CaseInsensitiveDict    以大小写不敏感字典返回 headers 数据
body    str
bytes
dict    如果是 json 格式,自动进行转换,如果时图片格式,进行 base64 转换,其它格式直接返回文本
raw_body    str    未被处理的 body 文本
status    int    请求状态
statusText    str    请求状态文本
除以上属性,还有以下属性,自行体会:

headersText、mimeType、requestHeaders、requestHeadersText、connectionReused、connectionId、remoteIPAddress、remotePort、fromDiskCache、fromServiceWorker、fromPrefetchCache、encodedDataLength、timing、serviceWorkerResponseSource、responseTime、cacheStorageCacheName、protocol、alternateProtocolUsage、securityState、securityDetails

FailInfo对象
FailInfo对象是DataPacket对象内用于保存连接失败信息的对象,有以下属性:

属性名称    数据类型    说明
errorText    str    错误信息文本
canceled    bool    是否取消
blockedReason    str    拦截原因
corsErrorStatus    str    cors 错误状态
动作链
动作链可以在浏览器上完成一系列交互行为,如鼠标移动、鼠标点击、键盘输入等。

ChromiumPage、WebPage、ChromiumTab、ChromiumFrame对象支持使用动作链。可以链式操作,也可以分开执行,每个动作执行即生效,无需perform()。这些操作皆为模拟,真正的鼠标不会移动,因此可以多个标签页同时操作。

有两种方式可以使用动作链,两者区别是,前者会等待页面加载完毕再执行,后者不会。

使用内置actions属性调用动作链: page.actions.
主动创建一个动作链对象,Actions (ChromiumPage|WebPage|ChromiumTab)
from DrissionPage import ChromiumPage
from DrissionPage.common import Actions

#1.使用内置actions属性
page = ChromiumPage()
page.get('https://www.baidu.com')
page.actions.move_to('#kw').click().type('DrissionPage')
page.actions.move_to('#su').click()


#2.使用新对象
page = ChromiumPage()
ac = Actions(page)
page.get('https://www.baidu.com')
ac.move_to('#kw').click().type('DrissionPage')
ac.move_to('#su').click()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
移动鼠标
[!NOTE]- move_to (): 此方法用于移动鼠标到元素中点,或页面上的某个绝对坐标。可设置偏移量,当带偏移量时,偏移量相对于元素左上角坐标。

初始化参数    类型    默认值    说明
ele_or_loc    ChrmoiumElement / str / Tuple[int, int]    必填    元素对象、文本定位符或绝对坐标,坐标为 tuple (int, int) 形式
offset_x    int    0    x 轴偏移量,向右为正,向左为负
offset_y    int    0    y 轴偏移量,向下为正,向上为负
duration    float    0.5    拖动用时,传入 0 即瞬间到达
返回类型    Actions    0    动作链对象本身
📌 move()
📌 up()
📌 down()
📌 left()
📌 right()

鼠标按键
📌 click()
📌 r_click()
📌 m_click()
📌 db_click()
📌 hold()
📌 release()
📌 r_hold()
📌 r_release()
📌 m_hold()
📌 m_release()

滚动滚轮
📌 scroll()

键盘按键和文本输入
📌 key_down()
📌 key_up()
📌 input()
📌 type()

截图和录制
页面截图
页面对象的get_screenshot()方法对页面进行截图,可对整个网页、可见网页、指定范围截图。
下面三个参数三选一,优先级:as_bytes>as_base64>path。

参数名称    类型    默认值    说明
path    str
Path    None    保存图片的路径,为None时保存在当前文件夹,如包含文件名的完整路径,name参数无效。
name    str    None    完整文件名,后缀可选'jpg'、'jpeg'、'png'、'webp',为None时以用 jpg 格式
as_bytes    str
True    None    是否以字节形式返回图片,可选'jpg'、'jpeg'、'png'、'webp'、None、True
不为None时path参数无效
为True时选用 jpg 格式
as_base64    str
True    None    是否以 base64 形式返回图片,可选'jpg'、'jpeg'、'png'、'webp'、None、True
不为None时path参数无效
为True时选用 jpg 格式
full_page    bool    False    是否整页截图,为True截取整个网页,为False截取可视窗口
left_top    Tuple[int, int]    None    截取范围左上角坐标
right_bottom    Tuple[int, int]    None    截取范围右下角坐标
返回类型    说明
bytes    as_bytes生效时返回图片字节
str    as_bytes和as_base64为None时返回图片完整路径
str    as_base64生效时返回 base64 格式的字符串
页面录像
页面对象.screencast:可以录取屏幕图片或视频。
📌 设置录制模式
📌 设置存放路径
📌 screencast.start()
📌 screencast.stop()
📌 注意事项
📌 示例

WebPage
WebPage()参数
mode: ‘d’ 或 ‘s’,即driver模式和session模式
timeout: 超时时间(秒),d模式时为寻找元素时间,s模式时为连接时间,默认10秒
chromium_options: Driver对象,只使用s模式时应传入False
session_or_options: Session对象或SessionOptions对象,只使用d模式时应传入False
from DrissionPage import WebPage, ChromiumOptions

class Obj(object):
    def __init__(self, page):
        self.page = page

    def main(self):
        pass

if __name__ == '__main__':
    co = ChromiumOptions().use_system_user_path()
    page = WebPage(mode='d', chromium_options=co)

    ob = Obj(page)
    ob.main()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
元素
元素定位
定位符语法简化
定位语法都有其简化形式
页面和元素对象都实现了__call__()方法,所以page.ele(‘…’)可简化为page(‘…’)
查找方法都支持链式操作

原写法    简化写法    说明
@id    #    表示 id 属性,简化写法只在语句最前面且单独使用时生效
@class    .    表示 class 属性,简化写法只在语句最前面且单独使用时生效
text    tx    按文本匹配
@text()    @tx()    按文本查找与 @ 或 @@ 配合使用时
tag    t    按标签类型匹配
xpath    x    用 xpath 方式查找元素
css    c    用 css selector 方式查找元素
# 查找tag为div的元素
ele = page.ele('tag:div')  # 原写法
ele = page('t:div')  # 简化写法

# 用xpath查找元素
ele = page.ele('xpath://xxxxx')  # 原写法
ele = page('x://xxxxx')  # 简化写法

# 查找text为'something'的元素
ele = page.ele('text=something')  # 原写法
ele = page('tx=something')  # 简化写法

# 根据 class 或 id 查找
page.ele('#ele_id')  # 等价于 page.ele('@id=ele_id')
page.ele('#:ele_id')  # 等价于 page.ele('@id:ele_id')
page.ele('.ele_class')  # 等价于 page.ele('@class=ele_class')
page.ele('.:ele_class')  # 等价于 page.ele('@class:ele_class')

# 根据 tag name 查找
page.ele('tag:li')  # 查找第一个 li 元素  
page.eles('tag:li')  # 查找所有 li 元素  

# 根据 tag name 及属性查找
page.ele('tag:div@class=div_class')  # 查找 class 为 div_class 的 div 元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
相对定位参数简化
相对定位时,有时需要获取当前元素后某个元素,而不关心该元素是什么类型,

ele2 = ele1.parent(2)
ele2 = ele1.next(2)('tx=xxxxx')
ele2 = ele1.before(2)
# 如此类推
1
2
3
4
匹配模式
模糊匹配 :
模糊匹配 :
匹配开头 ^
匹配结尾 $
# 获取name属性为'row1'的元素
ele = page.ele('@name=row1')

# 获取name属性包含'row1'的元素
ele = page.ele('@name:row1')

# 获取name属性以'row1'开头的元素
ele = page.ele('@name^ro')

# 获取name属性以'w1'结尾的元素
ele = page.ele('@name$w1')
1
2
3
4
5
6
7
8
9
10
11
基本方法
id 匹配符 # :表示id属性,只在语句最前面且单独使用时生效,可配合匹配模式使用。
类型匹配符 tag:表示元素的标签,只在语句最前面且单独使用时生效,可与@、@@或@|配合使用。tag:与tag=效果一致,没有tag^和tag$语法。
# 定位div元素
ele2 = ele1.ele('tag:div')

# 定位class属性为p_cls的p元素
ele2 = ele1.ele('tag:p@class=p_cls')

# 定位文本为"第二行"的p元素
ele2 = ele1.ele('tag:p@text()=第二行')

# 定位class属性为p_cls且文本为“第二行”的p元素
ele2 = ele1.ele('tag:p@@class=p_cls@@text()=第二行')

# 定位class属性为p_cls或文本为“第二行”的p元素
ele2 = ele1.ele('tag:p@|class=p_cls@|text()=第二行')

# 查找直接文本节点包含“二行”字符串的p元素
ele2 = ele1.ele('tag:p@text():二行')

# 查找内部文本节点包含“二行”字符串的p元素
ele2 = ele1.ele('tag:p@@text():二行')  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
属性
class 匹配符 .
# 查找class属性为p_cls的元素
ele2 = ele1.ele('.p_cls')

# 查找class属性'_cls'文本开头的元素
ele2 = ele1.ele('.^_cls')  

# 精确查找class属性为`p_cls1 p_cls2 `的元素
ele2 = ele1.ele('.p_cls1 p_cls2 ')

#如果某元素有多个类名,必须写 class 属性的完整值(类名的顺序也不能变)
# 模糊查找class属性含有类名 'p_cls2' 的元素
ele2 = ele1.ele('.:p_cls2')  
1
2
3
4
5
6
7
8
9
10
11
12
单属性匹配符 @:表示某个属性,只匹配一个属性。可单独使用,也可与tag配合使用。
# 查找name属性为row1的元素
ele2 = ele1.ele('@name=row1')

# 查找name属性包含row文本的元素,可以跟匹配模式
ele2 = ele1.ele('@name:row')


# 查找有name属性的元素
ele2 = ele1.ele('@name')

# 查找没有任何属性的元素
ele2 = ele1.ele('@')

# 查找email属性为abc@def.com的元素,有多个@也不会重复处理
ele2 = ele1.ele('@email=abc@def.com')

# 属性中有特殊字符的情形,匹配abc@def属性等于v的元素
ele2 = ele1.ele('css:div[abc\@def="v"]')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
多属性与匹配符 @@:匹配同时符合多个条件的元素时使用,每个条件前面添加@@作为开头。
多属性或匹配符@| :匹配符合多个条件中任一项的元素时使用,每个条件前面添加@|作为开头。
属性否定匹配符@! :用于否定某个条件,可与@@或@|混用,也可单独使用。
# 查找name属性为row1且class属性包含cls文本的元素
ele2 = ele1.ele('@@name=row1@@class:cls')
ele = page.ele('tag:div@@class=p_cls@@name=row1')

# 查找id属性为one或id属性为two的元素
ele2 = ele1.ele('@|id=one@|id=two')
ele = page.ele('tag:div@|class=p_cls@|name=row1')

# 匹配arg1等于abc且arg2不等于def的元素
page.ele('@@arg1=abc@!arg2=def')

# 匹配arg1等于abc或arg2不等于def的div元素
page.ele('t:div@|arg1=abc@!arg2=def')

# 匹配arg1不等于abc
page.ele('@!arg1=abc')

# 匹配没有arg1属性的元素
page.ele('@!arg1')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
文本
文本匹配符 text:
要匹配的文本,查询字符串如开头没有任何关键字,也表示根据传入的文本作模糊查找。
如果元素内有多个直接的文本节点,精确查找时可匹配所有文本节点拼成的字符串,模糊查找时可匹配每个文本节点。
如果要匹配的文本包含特殊字符(如’ ‘、’>'),需将其转换为十六进制形式,详见《语法速查表》一节。
# 查找文本为“第二行”的元素
ele2 = ele1.ele('text=第二行')

# 查找文本包含“第二”的元素
ele2 = ele1.ele('text:第二')

# 与上一行一致
ele2 = ele1.ele('第二')

# 匹配包含&nbsp;文本的元素
ele2 = ele1.ele('第\u00A0二')  # 需将&nbsp;转为\u00A0
1
2
3
4
5
6
7
8
9
10
11
文本匹配符 text():
作为查找属性时使用的文本关键字,必须与@或@@配合使用。
text在作为属性查找条件是改为text(),是为了避免遇到名为text的属性时产生冲突。
# 查找文本为“第二行”的元素
ele2 = ele1.ele('@text()=第二行')

# 查找文本包含“第二行”的元素
ele2 = ele1.ele('@text():二行')

# 查找文本以“第二”开头且class属性为p_cls的元素
ele2 = ele1.ele('@@text()^第二@@class=p_cls')

# 查找文本为“二行”且没有任何属性的元素(因第一个 @@ 后为空)
ele2 = ele1.ele('@@@@text():二行')

# 查找直接子文本包含“二行”字符串的元素
ele = page.ele('@text():二行')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@@text()的技巧
css和xpath
css selector 匹配符 css :表示用 css selector 方式查找元素。css:与css=效果一致,没有css^和css$语法。
# 查找 div 元素
ele2 = ele1.ele('css:.div')

# 查找 div 子元素元素,这个写法是本库特有,原生不支持
ele2 = ele1.ele('css:>div')  
1
2
3
4
5
xpath 匹配符 xpath
# 查找后代中第一个 div 元素
ele2 = ele1.ele('xpath:.//div')

# 和上面一行一样,查找元素的后代时,// 前面的 . 可以省略
ele2 = ele1.ele('xpath://div')

# 使用xpath获取div元素的class属性(页面元素无此功能)
ele_class_str = ele1.ele('xpath://div/@class')
1
2
3
4
5
6
7
8
selenium 的 loc 元组
from DrissionPage.common import By

# 查找id为one的元素
loc1 = (By.ID, 'one')
ele = page.ele(loc1)

# 按 xpath 查找
loc2 = (By.XPATH, '//p[@class="p_cls"]')
ele = page.ele(loc2)  
1
2
3
4
5
6
7
8
9
相对定位
父子元素
[!NOTE] parent(level_or_loc=1,index=1)获取父级元素

level_or_loc[int|str|Tuple[str, str]]:第几级父元素,从1开始,或用定位符在祖先元素中进行筛选
index [int] :当level_or_loc传入定位符,使用此参数选择第几个结果,从当前元素往上级数;当level_or_loc传入数字时,此参数无效
# 获取 ele1 的第二层父元素
ele2 = ele1.parent(2)

# 获取 ele1 父元素中 id 为 id1 的元素
ele2 = ele1.parent('#id1')
1
2
3
4
5
child()此方法返回当前元素的一个直接子节点,可指定筛选条件和第几个。
参数名称    类型    默认值    说明
locator    str
Tuple[str, str]
int    ''    用于筛选节点的查询语法,为int类型时index参数无效
index    int    1    查询结果中的第几个,从1开始,可输入负数表示倒数
timeout    float    None    无实际作用
ele_only    bool    True    是否只查找元素,为False时把文本、注释节点也纳入查找范围
children():此方法返回当前元素全部符合条件的直接子节点组成的列表,可用查询语法筛选。
参数名称    类型    默认值    说明
locator    str
Tuple[str, str]    ''    用于筛选节点的查询语法
timeout    float    None    无实际作用
ele_only    bool    True    是否只查找元素,为False时把文本、注释节点也纳入查找范围
前面
prev():获取前面的同级节点:此方法返回当前元素前面的某一个同级节点,可指定筛选条件和第几个。
prevs():返回当前元素前面全部符合条件的同级节点组成的列表,可用查询语法筛选。
before():返回当前元素前面的某一个符合条件的节点,可指定筛选条件和第几个。查找范围不限同级节点,而是整个 DOM 文档。
befores():返回当前元素前面全部符合条件的节点组成的列表,可用查询语法筛选。查找范围不限同级节点,而是整个 DOM 文档。
参数名称    类型    默认值    说明
locator    str
Tuple[str, str]
int    ''    用于筛选节点的查询语法,为int类型时index参数无效
index    int    1    查询结果中的第几个,从1开始,可输入负数表示倒数
timeout    float    None    无实际作用
ele_only    bool    True    是否只查找元素,为False时把文本、注释节点也纳入查找范围
# 获取 ele1 前面第一个兄弟元素
ele2 = ele1.prev()

# 获取 ele1 前面第 3 个兄弟元素
ele2 = ele1.prev(3)

# 获取 ele1 前面第 3 个 div 兄弟元素
ele2 = ele1.prev(3, 'tag:div')

# 获取 ele1 前面第一个文本节点的文本
txt = ele1.prev(1, 'xpath:text()')
1
2
3
4
5
6
7
8
9
10
11
后面
next() 获取后面的同级节点,也叫兄弟节点:
nexts():返回当前元素后面全部符合条件的同级节点组成的列表,可用查询语法筛选。
after():在后面文档中查找节点
afters():返回当前元素后面符合条件的全部节点组成的列表,可用查询语法筛选。查找范围不限同级节点,而是整个 DOM 文档
page('账号').after('t:input').input('123')
page('密码').after('t:input').input('456')

1
2
3
元素信息
与SessionElement共有信息
属性或方法    说明
html    此属性返回元素的 outerHTML 文本
inner_html    此属性返回元素的 innerHTML 文本
tag    此属性返回元素的标签名
text    此属性返回元素内所有文本组合成的字符串
raw_text    此属性返回元素内原始文本
texts()    此方法返回元素内所有直接子节点的文本,包括元素和文本节点
comments    此属性以列表形式返回元素内的注释
attrs    此属性以字典形式返回元素所有属性及值
attr()    此方法返回元素某个 attribute 属性值
link    此方法返回元素的 href 属性或 src 属性
page    此属性返回元素所在的总控页面对象
xpath    此属性返回当前元素在页面中 xpath 的绝对路径
css_path    此属性返回当前元素在页面中 css selector 的绝对路径
状态信息
状态信息藏在states属性中。元素对象.states

states.is_in_viewport:返回元素是否在视口中,以元素可以接受点击的点为判断。
states.is_whole_in_viewport:返回元素是否整个在视口中。
states.is_alive:返回当前元素是否仍可用。用于判断 d 模式下是否因页面刷新而导致元素失效。
states.is_checked:返回表单单选或多选元素是否选中。
states.is_selected:返回<select>元素中的项是否选中。
states.is_enabled:以布尔值返回元素是否可用。
states.is_displayed:返回元素是否可见。
states.is_covered:返回元素是否被其它元素覆盖。如被覆盖,返回覆盖元素的 id,否则返回False
states.has_rect:返回元素是否拥有大小和位置信息,有则返回四个角在页面上的坐标组成的列表,没有则返回False。
大小和位置
📌 rect.size
📌 rect.location
📌 rect.midpoint
📌 rect.click_point
📌 rect.viewport_location
📌 rect.viewport_midpoint
📌 rect.viewport_click_point
📌 rect.screen_location
📌 rect.screen_midpoint
📌 rect.screen_click_point
📌 rect.corners
📌 rect.viewport_corners
📌 rect.viewport_rect

保存元素
[!NOTE] src():返回元素src属性所使用的资源。

timeout=None:等待资源加载超时时间,为None时使用元素所在页面timeout属性
base64_to_bytes= True:为True时,如果是 base64 数据,转换为bytes格式
返回类型:base64 的可转为bytes返回,其它的以str返回。无资源的返回None。
[!NOTE] save():保存src()方法获取到的资源到文件。

path[str|Path]=None 文件保存路径,为None时保存到当前文件夹
name=[str]=None 文件名称,需包含后缀,为None时从资源 url 获取
timeout float None 等待资源加载超时时间,为None时使用元素所在页面timeout属性
rename bool True 遇到重名文件时是否自动重命名
import ddddocr
code = page('#randCode_icon').src()

ocr = ddddocr.DdddOcr(show_ad=False)
res = ocr.classification(code)

1
2
3
4
5
6
ShadowRoot属性
📌 tag
📌 html
📌 inner_html
📌 page
📌 parent_ele
📌 states.is_enabled
📌 states.is_alive

比较元素
元素截图
用于获取验证码人机验证码

元素对象.get_screenshot():对元素进行截图。
若元素范围超出视口,需 90 以上版本内核支持。
下面三个参数三选一,优先级:as_bytes>as_base64>path。
参数名称    类型    默认值    说明
path    str
Path    None    保存图片的路径,为None时保存在当前文件夹,包含文件名的完整路径,name参数无效。
name    str    None    完整文件名,后缀可选'jpg'、'jpeg'、'png'、'webp',为None时以用 jpg 格式
as_bytes    str
True    None    是否以字节形式返回图片,可选'jpg'、'jpeg'、'png'、'webp'、None、True
不为None时path和as_base64参数无效
为True时选用 jpg 格式
as_base64    str
True    None    是否以 base64 形式返回图片,可选'jpg'、'jpeg'、'png'、'webp'、None、True
不为None时path参数无效
为True时选用 jpg 格式
scroll_to_center    bool    True    截图前是否滚动到视口中央
返回类型    说明
bytes    as_bytes生效时返回图片字节
str    as_bytes和as_base64为None时返回图片完整路径
str    as_base64生效时返回 base64 格式的字符串
保存元素

元素交互
点击
输入
input():用于向元素输入文本或组合键,也可用于输入文件路径到上传控件。可选择输入前是否清空元素。
参数名称    类型    默认值    说明
vals    Any    False    文本值或按键组合
对文件上传控件时输入路径字符串或其组成的列表
clear    bool    False    输入前是否清空文本框
by_js    bool    False    是否用 js 方式输入,为True时不能输入组合键
元素的等待
📌 wait.displayed():等待元素从隐藏状态变成显示状态。元素隐藏是指元素在 DOM 内,但处于隐藏状态(即使在视口内且不被遮挡)。父元素隐藏时子元素也是隐藏的。
📌 wait.hidden():等待元素从显示状态变成隐藏状态。
📌 wait.deleted():等待元素被从 DOM 删除。
📌 wait.covered():用于等待元素被其它元素覆盖。
📌 wait.not_covered():用于等待元素不被其它元素覆盖。
📌 wait.enabled():用于等待元素变为可用状态。
📌 wait.disabled():用于等待元素变为不可用状态。
📌 wait.stop_moving():用于等待元素运动结束。如果元素没有大小和位置信息,会在超时时抛出NoRectError异常。
📌 wait.disable_or_deleted():用于等待元素变为不可用或被删除。
📌 wait():此方法用于等待若干秒。
scope为None时,效果与time.sleep()没有区别,等待指定秒数。
scope不为None时,获取两个参数之间的一个随机值,等待这个数值的秒数。
例子
多线程并发
并发编程-py
当你有多个链接需要打开时,使用多线程并发多开标签页

from concurrent.futures import ThreadPoolExecutor

with ThreadPoolExecutor(max_workers=3) as executor:
 
    # 通过executor的 map 获取已经完成的task的值
    for data in executor.map(get_html, urls):
        print("get {} page".format(data))

1
2
3
4
5
6
7
8

#坑

pyinstaller打包报错
ImportError: DLL load failed while importing _sqlite3: 找不到指定的模块。
1
python 内置了这个sqlite3.dll模块,而anaconda没有

把sqlite3.dll放到python环境中的DLLs目录下

C:\Users\wenke\.conda\envs\drission\DLLs
1
在pyinstaller的xxx.spec文件中添加DLLs目录

 binaries=[('C:\\Users\\wenke\\.conda\\envs\\drission\\DLLs','.')],
1
pyinstaller main.spec
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/qq_44744569/article/details/138244161

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值