大数据时代,各行各业对数据采集的需要日益增多,网络爬虫的使用也更为宽泛,越来越多的人开始学习网络爬虫这项技术,K 哥爬虫此前曾经推出不少爬虫进阶、逆向相干文章,为实现从易到难全方位笼罩,特设【0 根底学爬虫】专栏,帮忙小白疾速入门爬虫,本期为自动化工具 playwright 的应用。
概述
上期文章中讲到了自动化工具 Selenium 的根本应用办法,也介绍了 Selenium 的优缺点。Selenium 的性能十分弱小,反对所有古代浏览器。然而 Selenium 应用起来非常不不便,咱们须要提前装置好浏览器,而后下载对应版本的驱动文件,当浏览器更新后驱动文件也得随之更新。如果想要大规模且长期的采集数据,那么部署 Selenium 时环境配置会是一个大问题。因而本期咱们将介绍一款更加好用的自动化工具 Playwright。
Playwright 的应用
介绍
Playwright 是一个用于自动化 Web 浏览器测试和 Web 数据抓取的开源库。它由 Microsoft 开发,反对 Chrome、Firefox、Safari、Edge 和 WebKit 浏览器。Playwright 的一个次要特点是它可能在所有次要的操作系统(包含 Windows、Linux 和 macOS)上运行,并且它提供了一些弱小的性能,如跨浏览器测试、反对无头浏览器、并行执行测试、元素截图和模仿输出等。它次要有以下劣势:
- 兼容多个浏览器,而且所有浏览器都应用雷同的 API。
- 速度快、稳定性高,即便在大型、简单的 Web 应用程序中也能够运行。
- 反对无头浏览器,因而能够在没有可见界面的状况下运行测试,从而进步测试效率。
- 提供了丰盛的 API,以便于执行各种操作,如截图、模仿输出、拦挡网络申请等。
装置
应用 Playwright 须要 Python 版本在 3.7 以上。
装置 Playwright 能够间接应用 pip 工具:
pip install playwright
装置实现后须要进行初始化操作,装置所需的浏览器。
playwright install
执行上述指令时,Playwright 会主动装置多个浏览器(Chromium、Firefox 和 WebKit)并配置驱动,所以速度较慢。
应用
Playwright 反对同步与异步两种模式,这里离开来进行解说。
同步
应用 Playwright 时能够抉择启动装置的三种浏览器(Chromium、Firefox 和 WebKit)中的一种。
from playwright.sync_api import sync_playwright
# 调用 sync_playwright 办法,返回浏览器上下文管理器
with sync_playwright() as p:
# 创立谷歌浏览器示例,playwright 默认启动无头模式,设置 headless=False,即敞开无头模式
browser = p.chromium.launch(headless=False)
# 新建选项卡
page = browser.new_page()
# 跳转到指标网址
page.goto("http://baidu.com")
# 获取页面截图
page.screenshot(path='example.png')
# 打印页面的题目,也就是 title 节点中的文本信息
print(page.title())
# 敞开浏览器
browser.close()
# 输入:百度一下,你就晓得
能够看到,Playwright 的应用也比较简单,语法比拟简洁,而且浏览器的启动速度以及运行速度也很快。
异步
异步代码的编写办法与同步基本一致,区别在于同步调用的是 sync_playwright,异步调用的是 async_playwright。最终运行成果与同步统一。
import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
await page.goto("http://baidu.com")
# 打印网页源代码
print(await page.content())
await browser.close()
asyncio.run(main())
代码生成
Playwright 提供了代码生成性能,这个性能能够对咱们在浏览器上的操作进行录制并生成代码,它能够无效进步程序的编写效率。代码生成性能须要应用 Playwright 命令行中的 codegen 实现,codegen 命令存在如下主要参数:
-o:将生成的脚本保留到指定文件
–target:生成的语言,默认为 Python
–save-trace:记录会话的跟踪并将其保留到文件中
-b:要应用的浏览器,默认为 chromium
–timeout:设置页面加载的超时工夫
–user-agent:指定 UA
–viewport-size:指定浏览器窗口大小
咱们在命令行执行命令:playwright codegen -o script.py
执行命令后会弹出一个 chromium 浏览器与脚本窗口,当咱们在浏览器上进行操作时,脚本窗口会依据咱们的操作生成对应代码。当咱们操作完结后,敞开浏览器,在当前目录下会生成一个 script.py 文件,该文件中就是咱们在进行浏览器操作时,Playwright 录制的代码。咱们运行该文件,就会发现它在复现咱们之前的操作。
代码生成性能的实用性其实较为个别,它只能实现比较简单的操作,当遇到简单操作时,生成的代码就容易呈现问题。最好的形式是应用代码生成性能生成局部操作的代码,而后再手动去批改它生成的代码。
隔离
上一步中,咱们应用代码生成性能生成了一段代码,咱们会发现这段代码中应用到了一个 new_context 办法,通过这个办法创立了一个 content,而后再去进行其它操作。这个 new_content 办法其实是为了创立一个独立的全新上下文环境,它的目标是为了避免多个测试用例并行时各个用例间不受烦扰,当一个测试用例异样时不会影响到另一个。
browser = playwright.chromium.launch()
context = browser.new_context()
page = context.new_page()
定位器
Playwright 提供了多种定位器来帮忙开发中定位元素。
page.get_by_role():通过显式和隐式可拜访性属性进行定位。
page.get_by_text():通过文本内容定位。
page.get_by_label():通过关联标签的文本定位表单控件。
page.get_by_placeholder():按占位符定位输出。
page.get_by_alt_text():通过代替文本定位元素,通常是图像。
page.get_by_title():通过题目属性定位元素。
page.get_by_test_id():依据 data-testid 属性定位元素(能够配置其余属性)。
page.locator():拓展选择器,能够应用 CSS 选择器进行定位
应用定位器最好的形式就是上文中讲到的利用代码生成性能来生成定位代码,而后手动去批改,这里就不做尝试。
选择器
Playwright 反对 CSS、Xpath 和一些拓展选择器,提供了一些比拟不便的应用规定。
CSS 选择器
# 匹配 button 标签
page.locator('button').click()
# 依据 id 匹配, 匹配 id 为 container 的节点
page.locator('#container').click()
# CSS 伪类匹配,匹配可见的 button 按钮
page.locator("button:visible").click()
# :has-text 匹配任意外部蕴含指定文本的节点
page.locator(':has-text("Playwright")').click()
# 匹配 article 标签内蕴含 products 文本的节点
page.locator('article:has-text("products")').click()
# 匹配 article 标签下蕴含类名为 promo 的 div 标签的节点
page.locator("article:has(div.promo)").click()
Xpath
page.locator("xpath=//button").click()
page.locator('xpath=//div[@class="container"]').click()
其它
# 依据文本匹配,匹配文本内容蕴含 name 的节点
page.locator('text=name').click()
# 匹配文本内容为 name 的节点
page.locator("text='name'").click()
# 正则匹配
page.locator("text=/name\s\w+word").click()
# 匹配第一个 button 按钮
page.locator("button").locator("nth=0").click()
# 匹配第二个 button 按钮
page.locator("button").locator("nth=-1").click()
# 匹配 id 为 name 的元素
page.locator('id=name')
期待
当进行 click、fill 等操作时,Playwright 在采取行动之前会对元素执行一系列可操作性检测,以确保这些口头可能按预期进行。
如对元素进行 click 操作之前,Playwright 将确保:
元素附加到 DOM
元素可见
元素是稳固的,因为没有动画或实现动画
元素接管事件,因为没有被其余元素遮挡
元素已启用
即便 Playwright 曾经做了充分准备,然而也并不齐全稳固,在理论我的项目中仍旧容易呈现因页面加载导致事件没有失效等问题,为了防止这些问题,须要自行设置期待。
# 固定期待 1 秒
page.wait_for_timeout(1000)
# 期待事件
page.wait_for_event(event)
# 期待加载状态
page.get_by_role("button").click()
page.wait_for_load_state()
事件
增加 / 删除事件
from playwright.sync_api import sync_playwright
def print_request_sent(request):
print("Request sent:" + request.url)
def print_request_finished(request):
print("Request finished:" + request.url)
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
# 增加事件 发动申请时打印 URL
page.on("request", print_request_sent)
# 申请实现时打印 URL
page.on("requestfinished", print_request_finished)
page.goto("https://baidu.com")
# 删除事件
page.remove_listener("requestfinished", print_request_finished)
browser.close()
反检测
在 Selenium 的应用中,咱们讲到了自动化工具容易被网站检测,也提供了一些绕过检测的计划。这里咱们介绍一下 Playwright 的反检测计划。
以 https://bot.sannysoft.com/ 为例,咱们别离测试失常模式与无头模式下的检测后果。
失常模式:
无头模式:
能够看到,失常模式下 WebDriver 一栏报红,而无头模式下更是惨不忍睹,基本上所有特色都被检测到了。这些还只是最根本的检测机制,自动化工具的弱点就裸露的很显著了。
与 Selenium 一样,绕过检测次要还是针对网站的检测机制来解决,次要就是在页面加载之前通过执行 JS 代码来批改一些浏览器特色。以无头模式为例:
from playwright.sync_api import sync_playwright
with open('./stealth.min.js', 'r') as f:
js = f.read()
with sync_playwright() as p:
browser = p.chromium.launch()
# 增加 UserAgent
page = browser.new_page(user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
)
# 执行 JS 代码
page.add_init_script(js)
page.goto("https://bot.sannysoft.com/")
page.screenshot(path='example.png')
browser.close()
这里与 Selenium 反检测计划一样,执行 stealth.min.js 来暗藏特色(stealth.min.js 的起源与介绍参考上期文章)。最终后果如下图:
能够看到,与实在浏览器拜访基本一致了。
总结
与 Selenium 相比,Playwright 最大的长处就是不须要手动装置驱动,而且它领有更好的性能与更多的性能。因而 在爬虫畛域,Playwright 是更好的抉择。