Scrapy第十五篇:后起之秀-Playwright
Playwright 是微软在 2020 年初开源的新一代自动化测试工具,它的功能类似于 Selenium、Pyppeteer 等,它的功能非常强大,使用便捷简单,缺点是更新较快,市面上相关文档又少。官网:
目录
1.安装
2.初始化
3.基本使用
4.代码生成
5.选择器
6.事件监听
6.正则表达式很多时候,点击的url后面会附带参数,这个参数是变动的,这是后需要用正则去匹配最典型的情况是等待一个页面加载:page.wait_for_url(http://xxxxx?id=123456)从源码可以看出我们是可以传入正则表达式的:编辑
7.滑动翻页
8.并发
9.实例
10.使用模板
11.使用经验
1.安装
pip install playwright -i https://pypi.tuna.tsinghua.edu.cn/simple
2.初始化
playwright install
3.基本使用
Playwright 支持两种模式:同步、异步。
同步模式:
import time
from playwright.sync_api import sync_playwright
if __name__ == '__main__':
# 浏览器上下文管理器
with sync_playwright() as p:
# 启动谷歌浏览器(关闭无头模式)
driver = p.chromium.launch(headless=False)
# 新建页面
page = driver.new_page()
# 访问网址
page.goto('https://www.baidu.com')
print(page.title())
page.fill('xpath=//input[@id="kw"]', '杜兰特')
page.click('xpath=//input[@id="su"]')
# 关闭驱动
time.sleep(5)
driver.close()
异步模式:
import asyncio
from playwright.async_api import async_playwright
async def main():
# 浏览器上下文管理器
async with async_playwright() as p:
# 启动谷歌浏览器(关闭无头模式)
driver = await p.chromium.launch(headless=False)
# 新建页面
page = await driver.new_page()
# 访问网址
await page.goto('https://www.baidu.com')
title = await page.title()
print(title)
# 关闭驱动
await driver.close()
asyncio.run(main())
注意:with 用于上下文对象的管理,它可以返回一个上下文管理器,也就对应一个 PlaywrightContextManager 对象,无论运行期间是否抛出异常,它能够帮助我们自动分配并且释放 Playwright 的资源。
4.代码生成
Terminal执行:
playwright codegen -o script.py
操作浏览器后,右边会生产相应的代码预览
关闭浏览器后,会在同级目录生成script.py代码 ,可以直接执行。
5.选择器
import time
from playwright.sync_api import sync_playwright
if __name__ == '__main__':
# 浏览器上下文管理器
with sync_playwright() as p:
# 启动谷歌浏览器(关闭无头模式)
driver = p.chromium.launch(headless=False)
# 新建页面
page = driver.new_page()
# 访问网址
page.goto('https://www.baidu.com')
print(page.title())
# xpath选择器(推荐,不同的模拟器有不同的写法,但是xpath都是相通的,一招鲜吃遍天)
page.fill('xpath=//input[@id="kw"]', '杜兰特')
# ID选择器
page.click('#su')
time.sleep(2)
# class选择器
page.fill('.s_ipt', '欧文')
# 文本选择器
page.click('text=百度一下')
# 关闭驱动
time.sleep(2)
driver.close()
6.事件监听
Page 对象提供了一个 on 方法,它可以用来监听页面中发生的各个事件,比如 close、console、load、request、response 等等。一个典型的用法就是用来监听页面的ajax请求响应:
import time
import cchardet
from playwright.sync_api import sync_playwright, Response
# 监听Response回调函数
def handle_response(response: Response):
detect = cchardet.detect(response.body())
if detect['encoding']:
print(response.body().decode(detect['encoding']))
if __name__ == '__main__':
# 浏览器上下文管理器
with sync_playwright() as p:
# 启动谷歌浏览器(关闭无头模式)
driver = p.chromium.launch(headless=False)
# 新建页面
page = driver.new_page()
# 访问网址
page.goto('https://spa6.scrape.center/')
print(page.title())
# 监听网络请求的Response
page.on('response', handle_response)
# 等待网络请求加载完毕
page.wait_for_load_state('networkidle')
time.sleep(2)
driver.close()
" class="reference-link">6.正则表达式 很多时候,点击的url后面会附带参数,这个参数是变动的,这是后需要用正则去匹配 最典型的情况是等待一个页面加载:page.wait_for_url(http://xxxxx?id=123456) 从源码可以看出我们是可以传入正则表达式的:
使用示例:
page.wait_for_url(re.compile("https://www.abcd.xyz/web/index[\s\S]*"))
7.滑动翻页
page.locator("body").press("PageDown")
8.并发
import asyncio
import time
from playwright.async_api import async_playwright
async def run(url):
async with async_playwright() as playwright:
# create a chromium browser instance
chromium = playwright.chromium
# browser = await chromium.launch()
# create a bowser instance which headless is true
browser = await chromium.launch(headless=False)
# create two isolated browser contexts
user_context = await browser.new_context()
page = await user_context.new_page()
await page.goto(url)
await page.fill('xpath=//input[@id="kw"]', '杜兰特')
await page.click('xpath=//input[@id="su"]')
time.sleep(10)
# await page2.goto('https://www.baidu.com')
async def main():
tasks = []
urls = ['https://www.baidu.com', 'https://www.baidu.com', 'https://www.baidu.com']
for url in urls:
task = asyncio.ensure_future(run(url))
tasks.append(task)
await asyncio.gather(*tasks)
if __name__ == '__main__':
asyncio.run(main())
9.实例
"""
同步模式
"""
import time
from playwright.sync_api import sync_playwright, Page, Locator
def handle_business(page: Page, url):
"""
逻辑处理
:param page: 页面实例
:param url: 访问地址
:return:
"""
page.goto(url)
# 定位输入框
"""
定位!
1.xpath定位:【搜索框】locator_input = page.locator('xpath=//input[@id="kw"]')
2.元素属性定位:【搜索框】locator_input = page.locator('[name="wd"]')后者locator_input = page.locator('[class="s_ipt"]')
3.本文定位:【搜索按钮】locator_submit_button = page.locator('text="百度一下"')
4.id定位:【搜索按钮】locator_submit_button = page.locator('#su')
5.CSS定位:略
6.伪类①:is【如果定位不到text="百度一下",则定位#su】locator_submit_button = page.locator(':is([text="百度一下"]),#su')
7.伪类②:has
8.伪类③:hans-text
"""
locator_input = page.locator('[class="s_ipt"]', ).filter()
"""
页面操作!
1.page.goto("https://example.com") # 前往页面
2.page.go_back(**kwargs) #前进
3.page.go_forward(**kwargs) # 后退
4.page.screenshot(path="screenshot.png") 截图
5.print(page.title()) # 打印当前页标题
6.print(page.url()) # 打印当前页URL
7.page.reload(**kwargs) # 重新加载当前页面
"""
# 填写
locator_input.fill('SpringBoot')
# 定位提交按钮
locator_submit_button: Locator = page.locator(':is([text="百度一下"]),#su')
# 鼠标单击
locator_submit_button.click()
"""
等待元素!
1.等待元素:page.wait_for_selector(selector="[class='page-item_M4MDr pc']", strict=False, state="visible", timeout=5000)
state:
- `attached` - 等待元素出现在DOM中
- `detached` - 等待元素消失在DOM中
- `visible` - 等待元素可访问
- `hidden` - 等待元素隐藏
strict:断言选择器元素唯一。
2.等待固定时间:page.wait_for_timeout(1000)
3.等待状态:page.wait_for_load_state(state="networkidle")
state:
- `domcontentloaded` - 等待DOM加载完毕
- `load` - 等待加载事件完毕
- `networkidle` - 等待网络闲置至少500ms(即网络加载完毕)
"""
page.wait_for_load_state(state="networkidle")
"""
元素操作!
1.文本输入:locator_input.fill('SpringBoot')
2.获取节点属性:attribute = page.get_attribute("#su", "type")
3.点击:locator_submit_button.click()或者page.click("#su")
"""
time.sleep(50)
if __name__ == '__main__':
# 浏览器上下文管理器
with sync_playwright() as p:
# 创建浏览器驱动
browser = p.chromium.launch(headless=False)
# 创建浏览器实例
context = browser.new_context()
# 创建页面实例
page = context.new_page()
handle_business(page, 'https://www.baidu.com/')
10.使用模板
import time
from playwright.sync_api import sync_playwright
if __name__ == '__main__':
# 浏览器上下文管理器
with sync_playwright() as p:
# 启动谷歌浏览器(关闭无头模式)
driver = p.chromium.launch(headless=False, args=["--start-maximized"])
# 全屏
context = driver.new_context(no_viewport=True)
# 新建页面
page = context.new_page()
# 这里使用生成器生成!!!!TODO
# 关闭驱动
time.sleep(10)
context.close()
driver.close()
11.使用经验
①最好不要去手写,太影响效率,最好是使用生成器,然后复制进模板进行修改。
②生成器生成的代码,往往无法直接使用,因为很多定位器是动态的,无法使用,我们需要把动态的定位器换成固定的定位器。
③有些元素只有悬停才会出现,我们可以使用hover()
page1.get_by_role("link", name="系统维护").hover()
④有些元素找不到、定位不到,可能是加载太慢了,我们可以先用xpath定位,等待元素出现
# 先等待元素
page1.wait_for_selector(
selector='//div[@class="am-modal-dialog" and @style="width: 540px; height: 150px;"]//span[@class="am-modal-btn"]')
# 再获取元素
selector = page1.query_selector(
selector='//div[@class="am-modal-dialog" and @style="width: 540px; height: 150px;"]//span[@class="am-modal-btn"]')
# 最后操作元素
selector.click()
⑤在循环里面做好异常捕获,并在捕获中将界面打回新一轮的起点。
⑥有时候跑得太快,下拉框没有选择进去,可以多执行几次。
page1.frame_locator("iframe[style=\"min-height:322px\"]").locator(
"select[name=\"orgCategory\"]").select_option(
f"{number}")
page1.frame_locator("iframe[style=\"min-height:322px\"]").locator(
"select[name=\"orgCategory\"]").select_option(
f"{number}")
page1.frame_locator("iframe[style=\"min-height:322px\"]").locator(
"select[name=\"orgCategory\"]").select_option(
f"{number}")
page1.get_by_text("确定").click()
还没有评论,来说两句吧...