DrissionPage官网

一些例子

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

创建页面对象

初始化参数:

初始化参数

类型

默认值

说明

session_or_options

Session
SessionOptions

None

传入Session对象时使用该对象收发数据包;传入SessionOptions对象时用该配置创建Session对象;为None则从 ini 文件读取

timeout

float

None

连接超时时间,为None则从配置文件中读取

直接创建
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()

参数名称

类型

默认值

说明

url

str

必填

目标 url

show_errmsg

bool

False

连接出错时是否显示和抛出异常

retry

int

None

重试次数,为None时使用页面参数,默认 3

interval

float

None

重试间隔(秒),为None时使用页面参数,默认 2

timeout

float

None

加载超时时间(秒)

**kwargs

-

None

连接所需其它参数,具体见 requests 用法

**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二')  # 匹配包含&nbsp;文本的元素,需将&nbsp;转为\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')

写法

说明

示例

@tag()

标签名

<div id="one">中的div

@****

标签体中的属性

<div id="one">中的id,写作'@id'

@text()

元素文本

<p class="p_cls">第三行</p>中的'第三行'

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)

之后的内容最好去官网看

🚤 访问网页 | DrissionPage官网

  • 访问网页

  • 获取网页信息

  • 页面交互

  • 获取元素信息

  • 元素交互

  • 等待

  • 文件上传

  • 标签页操作

  • 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'