DrissionPage一些基础,主要是SessionPage
一些例子
from DrissionPage import ChromiumPage
# 创建页面对象,并启动或接管浏览器
page = ChromiumPage()
# 跳转到登录页面
page.get('https://gitee.com/login')#打开后执行后续操作,可以修改等待策略
# 定位到账号文本框,获取文本框元素
ele = page.ele('#user_login')# '#id' ele方法查找元素
# 输入对文本框输入账号
ele.input('19113781116')
# 定位到密码文本框并输入密码
page.ele('#user_password').input('wanghao376514293')#两种书写方式
# 点击登录按钮
page.ele('@value=登 录').click()# '@属性名'
from DrissionPage import SessionPage
# 创建页面对象
page = SessionPage()
# 爬取3页
for i in range(1, 4):
# 访问某一页的网页
page.get(f'https://gitee.com/explore/all?page={i}')#f嵌入表达式和变量
# 获取所有开源库<a>元素列表
links = page.eles('.title project-namespace-path')
# 遍历所有<a>元素
for link in links:
# 打印链接信息
print(f'{link.text}, {link.link}/n')
# 导入
from DrissionPage import SessionPage
# 创建页面对象
page = SessionPage()
# 访问网页
page.get('https://gitee.com/explore/all')
# 在页面中查找元素
items = page.eles('t:h3')
# 遍历元素
for item in items[:-1]:
# 获取当前<h3>元素下的<a>元素
lnk = item('tag:a')
# 打印<a>元素文本和href属性
print(lnk.text, lnk.link)
一些方法
ele方法
查找第一个匹配元素,返回一个ChromiumPage对象,内置等待,默认超时10秒
eles方法
查找多个符合条件的元素,返回list
s_ele方法,s_eles方法
from DrissionPage import ChromiumPage
page = ChromiumPage()
# 在页面中查找元素,获取其静态版本
ele1 = page.s_ele('search text')
# 在动态元素中查找元素,获取其静态版本
ele = page.ele('search text')
ele2 = ele.s_ele()
# 获取页面元素的静态副本(不传入参数)
s_page = page.s_ele()
# 获取动态元素的静态副本
s_ele = ele.s_ele()
# 在静态副本中查询下级元素(因为已经是静态元素,用ele()查找结果也是静态)
ele3 = s_page.ele('search text')
ele4 = s_ele.ele('search text')
from DrissionPage import WebPage
page = WebPage()
for ele in page.s_eles('search text'):
print(ele.text)
一些思路
要爬什么?id?属性名?
爬的东西有多少?有多页的话,怎么表现出来的?url里?
SessionPage
创建页面对象
初始化参数:
直接创建
from DrissionPage import SessionPage
page = SessionPage()
默认读取ini文件配置
通过配置信息创建
可以用SessionOptions
# 导入 SessionOptions
from DrissionPage import SessionPage, SessionOptions
# 创建配置对象,并设置代理信息
so = SessionOptions().set_proxies(http='127.0.0.1:1080')
# 用该配置创建页面对象
page = SessionPage(session_or_options=so)
指定ini
from DrissionPage import SessionPage, SessionOptions
# 创建配置对象时指定要读取的ini文件路径
so = SessionOptions(ini_path=r'./config1.ini')
# 使用该配置对象创建页面
page = SessionPage(session_or_options=so)
传递控制权
# 创建一个页面
page1 = SessionPage()
# 获取页面对象内置的Session对象
session = page1.session
# 在第二个页面对象初始化时传递该对象
page2 = SessionPage(session_or_options=session)
访问网页
GET()
**kwargs参数与 requests 中该参数使用方法一致,但有一个特点,如果该参数中设置了某一项(如headers),该项中的每个项会覆盖从配置中读取的同名项,而不会整个覆盖。
就是说,如果想继续使用配置中的headers信息,而只想修改其中一项,只需要传入该项的值即可。这样可以简化代码逻辑。
from DrissionPage import SessionPage
page = SessionPage()
page.get('http://g1879.gitee.io/drissionpage')
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)
POST()
from DrissionPage import SessionPage
page = SessionPage()
data = {'username': '****', 'pwd': '****'}
page.post('http://example.com', data=data)
# 或
page.post('http://example.com', json=data)
data和json均可接受str和dict格式的数据,即字符串或者字典,具体看服务器要求
其他
本库只针对常用的 get 和 post 方式作了优化,但也可以通过提取页面对象内的Session对象以原生 requests 代码方式执行其它请求方式。
from DrissionPage import SessionPage
page = SessionPage()
# 获取内置的 Session 对象
session = page.session
# 以 head 方式发送请求
response = session.head('https://www.baidu.com')
print(response.headers)
获取页面信息
url,str
title,str
raw_data:元素数据,bytes
html:整个html文本,str
json:返回json,类型:dict
user_agent:返回user_agent信息,类型:str
运行参数
# 创建页面对象时指定
page = SessionPage(timeout=5)
# 修改 timeout
page.timeout = 20
# 修改重试次数
page.retry_times = 5
# 修改重试等待间隔时间
page.retry_interval = 1.5
cookies()
from DrissionPage import SessionPage
page = SessionPage()
page.get('http://www.baidu.com')
page.get('http://gitee.com')
for i in page.cookies(as_dict=False, all_domains=True):
print(i)
其他
session:返回session对象
response:返回Response对象
查找元素的一些技巧
div1 = tab.ele('#one') # 获取 id 为 one 的元素
p1 = tab.ele('@name=row1') # 获取 name 属性为 row1 的元素
div2 = tab.ele('第二个div') # 获取包含“第二个div”文本的元素
div_list = tab.eles('tag:div') # 获取所有div元素
div1 = tab.ele('#one') # 获取到一个元素div1
p_list = div1.eles('tag:p') # 在div1内查找所有p元素
div2 = div1.next() # 获取div1后面一个元素
tab.ele('@id=one') # 获取第一个id为one的元素
tab.ele('@tag()=div') # 获取第一个div元素
tab.ele('@text()=第一行') # 获取第一个文本为“第一行”的元素
ele = tab.ele('@@class=p_cls@@text()=第三行') # 查找class为p_cls且文本为“第三行”的元素
eles = tab.eles('@|id=row1@|id=row2') # 查找所有id为row1或id为row2的元素
ele = tab.ele('@!id=one') # 获取第一个id不等于“one”的元素
ele = tab.ele('@!class') # 匹配没有class属性的元素
# 匹配class等于p_cls且id不等于row1的元素
tab.ele('@@class=p_cls@!id=row1')
# 匹配class等于p_cls或id不等于row1的元素
tab.ele('@|class=p_cls@!id=row1')
ele = tab.ele('@id=row1') # 获取id属性为'row1'的元素
ele = tab.ele('@id:ow') # 获取id属性包含'ow'的元素
ele = tab.ele('@id^row') # 获取id属性以'row'开头的元素
ele = tab.ele('@id$w1') # 获取id属性以'w1'结尾的元素
ele = tab.ele('#one') # 查找id为one的元素
ele = tab.ele('#=one') # 和上面一行一致
ele = tab.ele('#:ne') # 查找id属性包含ne的元素
ele = tab.ele('#^on') # 查找id属性以on开头的元素
ele = tab.ele('#$ne') # 查找id属性以ne结尾的元素
ele = tab.ele('.p_cls') # 查找class属性为p_cls的元素
ele = tab.ele('.=p_cls') # 与上一行一致
ele = tab.ele('.:_cls') # 查找class属性包含_cls的元素
ele = tab.ele('.^p_') # 查找class属性以p_开头的元素
ele = tab.ele('.$_cls') # 查找class属性以_cls结尾的元素
ele = tab.ele('text=第二行') # 查找文本为“第二行”的元素
ele = tab.ele('text:第二') # 查找文本包含“第二”的元素
ele = tab.ele('第二') # 与上一行一致
ele = tab.ele('第\u00A0二') # 匹配包含 文本的元素,需将 转为\u00A0
ele = tab.ele('tag:div') # 查找第一个div元素
ele = tab.ele('tag:p@class=p_cls') # 与单属性查找配合使用
ele = tab.ele('tag:p@@class=p_cls@@text()=第二行') # 与多属性查找配合使用
'''
tag:div@text():abc 和 tag:div@@text():abc 是有区别的,前者只在div的直接文本节点搜索,后者搜索div的整个内部。
'''
ele2 = ele1.ele('xpath:.//div') # 查找后代中第一个 div 元素
ele2 = ele1.ele('xpath://div') # 和上面一行一样,查找元素的后代时,// 前面的 . 可以省略
ele_class_str = ele1.ele('xpath://div/@class') # 使用xpath获取div元素的class属性(页面元素无此功能)
ele = tab.active_ele#获取页面焦点元素
iframe = page.get_frame(1) # 获取页面中第一个iframe元素
iframe = page.get_frame('#theFrame') # 获取页面id为theFrame的iframe元素对象
# 获取一个 shadow-root 元素
sr_ele = page.ele('#app').shadow_root
# 在该元素下查找下级元素
ele1 = sr_ele.ele('tag:div')
# 用相对定位获取其它元素
ele1 = sr_ele.parent(2)
ele1 = sr_ele.next('tag:div', 1)
ele1 = sr_ele.after('tag:div', 1)
eles = sr_ele.nexts('tag:div')
# 定位下级元素中的 shadow+-root 元素
sr_ele2 = sr_ele.ele('tag:div').shadow_root
# 获取 ele1 的第二层父元素
ele2 = ele1.parent(2)
# 获取 ele1 父元素中 id 为 id1 的元素
ele2 = ele1.parent('#id1')
# 获取 ele1 后面第一个兄弟元素
ele2 = ele1.next()
# 获取 ele1 后面第 3 个兄弟元素
ele2 = ele1.next(3)
# 获取 ele1 后面第 3 个 div 兄弟元素
ele2 = ele1.next('tag:div', 3)
# 获取 ele1 后面第一个文本节点的文本
txt = ele1.next('xpath:text()', 1)
# 获取 ele1 后面所有兄弟元素
eles = ele1.nexts()
# 获取 ele1 后面所有 div 兄弟元素
divs = ele1.nexts('tag:div')
# 获取 ele1 后面的所有文本节点
txts = ele1.nexts('xpath:text()')
# 获取 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()')
# 获取 ele1 前面所有兄弟元素
eles = ele1.prevs()
# 获取 ele1 前面所有 div 兄弟元素
divs = ele1.prevs('tag:div')
child()
此方法返回当前元素的一个直接子节点,可指定筛选条件和第几个。
children()
此方法返回当前元素全部符合条件的直接子节点组成的列表,可用查询语法筛选。
获取元素信息
ele为下面的一个对象:
<div id="div1" class="divs">Hello World!
<p>行元素</p>
<!--这是注释-->
</div>
print(ele.html)
'''
<div id="div1" class="divs">Hello World!
<p>行元素</p>
<!--这是注释-->
</div>
'''
print(ele.inner_html)
'''
Hello World!
<p>行元素</p>
<!--这是注释-->
'''
print(ele.tag)#div
print(ele.text)
'''
Hello World!
行元素
'''
print(ele.raw_text)
'''
Hello World!
行元素
'''
print(e.texts())
print(e.texts(text_node_only=True))
'''
['Hello World!', '行元素']
['Hello World!']
'''
print(ele.comments)
'''
[<!--这是注释-->]
'''
print(ele.attrs)
'''
{'id': 'div1', 'class': 'divs'}
'''
print(ele.attr('id'))
'''
div1
'''
page = ele.page#返回页面对象
print(ele.xpath)
'''
/html/body/div 当前元素xpath的绝对路径
'''
from DrissionPage import SessionPage
page = SessionPage()
page.get('https://www.baidu.com')
eles = page('#s-top-left').eles('t:a')
print(eles.get.texts()) # 获取所有元素的文本
页面设置
用SessionOptions对象管理SessionPage对象的初始配置,启动后再修改就没有效果了
from DrissionPage import SessionPage, SessionOptions
# 创建配置对象(默认从 ini 文件中读取配置)
so = SessionOptions()
# 设置代理
so.set_proxies('http://localhost:1080')
# 设置 cookies
cookies = ['key1=val1; domain=****', 'key2=val2; domain=****']
so.set_cookies(cookies)
# 以该配置创建页面对象
page = SessionPage(session_or_options=so)
set_headers
set_a_header
remove_a_header
clear_headers
......
# 保存当前读取的ini文件
so.save()
# 把当前配置保存到指定的路径
so.save(path=r'D:\tmp\settings.ini')
so.save_to_default()#保存到固定ini默认文件
ChromiumPage
启动或接管浏览器
无头模式注意:程序关闭后,浏览器进程仍然存在,看不见而已
创建
ChromiumPage
对象时会在指定端口启动浏览器,或接管该端口已有浏览器。默认情况下,程序使用 9222 端口,浏览器可执行文件路径为
'chrome'
。如路径中没找到浏览器可执行文件,Windows 系统下程序会在注册表中查找路径。
如果都没找到,则要用下文介绍的手动配置方法。
直接创建时,程序默认读取 ini 文件配置,如 ini 文件不存在,会使用内置配置。
# 接管9333端口的浏览器,如该端口空闲,启动一个浏览器
page = ChromiumPage(9333)
page = ChromiumPage('127.0.0.1:9333')
# 导入 ChromiumOptions
from DrissionPage import ChromiumPage, ChromiumOptions
# 创建浏览器配置对象,指定浏览器路径
co = ChromiumOptions().set_browser_path(r'D:\chrome.exe')
# 用该配置创建页面对象
page = ChromiumPage(addr_or_opts=co)
page = ChromiumPage(addr_or_opts='127.0.0.1:9333')
from DrissionPage import ChromiumPage, ChromiumOptions
# 创建配置对象时指定要读取的ini文件路径
co = ChromiumOptions(ini_path=r'./config1.ini')
# 使用该配置对象创建页面
page = ChromiumPage(addr_or_opts=co)
#手动打开的浏览器
from DrissionPage import ChromiumPage, ChromiumOptions
co = ChromiumOptions().set_local_port(9222)
page = ChromiumPage(addr_or_opts=co)
#bat文件启动浏览器,txt文本里写入后改后缀bat
"D:\chrome.exe" --remote-debugging-port=9222 --remote-allow-origins=*
#双击运行,在9222端口开启一个浏览器
from DrissionPage import ChromiumPage, ChromiumOptions
co = ChromiumOptions().set_local_port(9222)
page = ChromiumPage(addr_or_opts=co)
from DrissionPage import ChromiumPage, ChromiumOptions
# 创建多个配置对象,每个指定不同的端口号和用户文件夹路径
do1 = ChromiumOptions().set_paths(local_port=9111, user_data_path=r'D:\data1')
do2 = ChromiumOptions().set_paths(local_port=9222, user_data_path=r'D:\data2')
# 创建多个页面对象
page1 = ChromiumPage(addr_or_opts=do1)
page2 = ChromiumPage(addr_or_opts=do2)
# 每个页面对象控制一个浏览器
page1.get('https://www.baidu.com')
page2.get('http://www.163.com')
#空闲端口和临时文件夹
from DrissionPage import ChromiumPage, ChromiumOptions
co1 = ChromiumOptions().auto_port()
co2 = ChromiumOptions().auto_port()
page1 = ChromiumPage(addr_or_opts=co1)
page2 = ChromiumPage(addr_or_opts=co2)
page1.get('https://www.baidu.com')
page2.get('http://www.163.com')
#使用系统浏览器用户目录
#每次启动时配置
from DrissionPage import ChromiumPage, ChromiumOptions
co = ChromiumOptions().use_system_user_path()
page = ChromiumPage(co)
#使用ini文件
from DrissionPage import ChromiumOptions
ChromiumOptions().use_system_user_path().save()
#全新的浏览器
#要么使用auto_port
#要么手动指定
from DrissionPage import ChromiumPage, ChromiumOptions
co = ChromiumOptions().set_local_port(9333).set_user_data_path(r'C:\tmp')
page = ChromiumPage(co)
之后的内容最好去官网看
访问网页
获取网页信息
页面交互
获取元素信息
元素交互
等待
文件上传
标签页操作
iframe操作
监听网络数据
动作链
截图和录像
浏览器启动设置
none模式技巧
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) # 打印数据包正文
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
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() # 主动停止加载
页面交互
一个 Tab 对象(ChromiumTab和WebPageTab)控制一个浏览器的标签页,是页面控制的主要单位。
page.set.blocked_urls('*.css*') # 设置不加载css文件
元素交互
# 对ele元素进行模拟点击,如判断被遮挡也会点击
ele.click()
# 用js方式点击ele元素,无视遮罩层
ele.click(by_js=True)
# 如元素不被遮挡,用模拟点击,否则用js点击
ele.click(by_js=None)
# 点击元素右上方 50*50 的位置
ele.click.at(50, -50)
# 点击元素上中部,x相对左上角向右偏移50,y保持在元素中点
ele.click.at(offset_x=50)
# 和click()一致,但没有重试功能
ele.click.at()
#组合键
from DrissionPage.common import Keys
ele.input((Keys.CTRL, 'a', Keys.DEL)) # ctrl+a+del
ele.input(Keys.CTRL_A) # 全选
# 悬停在元素右上方 50*50 的位置
ele.hover(50, -50)
# 悬停在元素上中部,x 相对左上角向右偏移50,y 保持在元素中点
ele.hover(offset_x=50)
# 悬停在元素中点
ele.hover()
多例
#启动多例
from DrissionPage.common import Settings
Settings.singleton_tab_obj = False
多标签页协同
from DrissionPage import ChromiumPage
page = ChromiumPage()
page.get('https://gitee.com/explore/all')
links = page.eles('t:h3')
for link in links[:-1]:
# 点击链接并获取新标签页对象
new_tab = link.click.for_new_tab()
# 等待新标签页加载
new_tab.wait.load_start()
# 打印标签页标题
print(new_tab.title)
# 关闭除列表页外所有标签页
page.close_tabs(others=True)
监听
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
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
动作链
from DrissionPage import ChromiumPage
from DrissionPage.common import Actions
page = ChromiumPage()
ac = Actions(page)
page.get('https://www.baidu.com')
ac.move_to('#kw').click().type('DrissionPage')
ac.move_to('#su').click()
from DrissionPage import ChromiumPage
tab = ChromiumPage()
tab.get('https://www.baidu.com')
tab.actions.click('#kw').input('DrissionPage')
'''
type()与input()区别在于前者模拟按键输入,逐个字符按下和提起,后者直接输入一整段文本。
'''
# 键入一段文本
tab.actions.type('text')
# 键入多段文本
tab.actions.type(('ab', 'cd'))
# 光标向左移动一位再键入文本
tab.actions.type((Keys.LEFT, 'abc'))
# 输入快捷键
tab.actions.type(Keys.CTRL_A)
浏览器启动设置
from DrissionPage import WebPage, ChromiumOptions
# 创建配置对象(默认从 ini 文件中读取配置)
co = ChromiumOptions()
# 设置不加载图片、静音
co.no_imgs(True).mute(True)
# 以该配置创建页面对象
page = WebPage(chromium_options=co)
from DrissionPage import ChromiumOptions, ChromiumPage
co = ChromiumOptions()
co.incognito() # 匿名模式
co.headless() # 无头模式
co.set_argument('--no-sandbox') # 无沙盒模式
page = ChromiumPage(co)
# 设置启动时最大化
co.set_argument('--start-maximized')
# 设置初始窗口大小
co.set_argument('--window-size', '800,600')
# 使用来宾模式打开浏览器
co.set_argument('--guest')
# 删除--start-maximized参数
co.remove_argument('--start-maximized')
# 删除--window-size参数
co.remove_argument('--window-size')
下载
from DrissionPage import ChromiumPage
page = ChromiumPage()
page.set.download_path('save_path') # 设置文件保存路径
page.set.download_file_name('file_name') # 设置重命名文件名
page('t:a').click() # 点击一个会触发下载的链接
page.wait.download_begin() # 等待下载开始
page.wait.downloads_done() # 等待下载结束
from DrissionPage import SessionPage
page = SessionPage()
url = 'https://www.baidu.com/img/flexible/logo/pc/result.png'
save_path = r'C:\download'
res = page.download(url, save_path)
print(res)
注意
程序无法接管一个已经弹出了提示框的浏览器或标签页。
有些文本框可以接收回车代替点击按钮,可以直接在文本末尾加上'\n'
。