新一代爬取JavaScript渲染页面的利器-playwright(一)

Playwright的使用

  Playwright是微软在2020年初开源的一款新一代自动化测试工具,其功能和**Selenium**、Pyppeteer类似,都可以驱动浏览器进行自动化操作,但是也具备了Selenium、Pyppeteer不具备的更好的API,是新一代爬取JavaScrip渲染页面的利器。

1.Playwright的特点

  • Playwright支持当前所有的主流浏览器,提供完善的自动化控制API。
  • Playwright支持移动端页面测试,使用设备模拟技术,可以在移动web浏览器中测试响应式的web应用程序。
  • Playwright支持所有浏览器的无头模式和非无头模式。
  • Playwright安装配置比较简单,安装过程中会自动安装对应的驱动,无需额外配置WebDriver等。
  • Playwright提供和自动等待相关的API,在页面加载时会自动等待对应的节点加载,大大减少了API编写的复杂度。

2.安装

  首先,确保python版本大于或等于3.7。

pip3 install playwright

  安装完成后执行初始化操作。

playwright install

  这是会自动安装Chromium、Firefox、WebKit浏览器和一些驱动。

3。基本使用

  Playwright支持两种编写模式,一种是和Pyppetter一样的异步模式,一种是和Selenium一样的同步模式,可以根据不同的实际需求来进行选择。

# 同步模式
# 调用了sync_playwright方法,该方法返回值是PlaywrightContext,可以理解为浏览器上下文管理器
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    for browser_type in [p.chromium,p.firefox,p.webkit]:
        # 不把lauch的headless设置为False,默认为无头浏览器
        browser = browser_type.launch(headless=False)
        # 新建选项卡,返回page对象
        page = browser.new_page()
        page.goto('http://www.baidu.com/')
        # 截图并定义文件名称
        page.screenshot(path=f'screenshot-{browser_type.name}.png')
        # title方法返回页面标题
        print(page.title())
        browser.close()

  运行上面代码可以看到chromium、firefox、webkit三个浏览器依次启动,启动后加载百度首页,加载完成后生成截图,然后打印页面标题到控制台。
  当然,除了同步模式,playwright还提供了支持异步模式的API,如果项目中使用了asyncio关键字,就应该使用异步模式。

import asyncio
from playwright.async.api import async_playwright

async def main():
    async with async_playwright() as p:
        for browser_type in [p.chromium,p.firefox,p.webkit]:
            browser = await browser_type.launch()
            page = await browser.new_page()
            await page.goto('https://www.baidu.com')
            await page.screenshot(path=f'screenshot-{browser_type.name}.png')
            print(await page.title())
            await browser.close()

asyncio.run(main())

  可以看到和同步模式基本一样,只不过导入方法改为async_playwright方法,不再是sync_playwright
方法,以及添加了async/await关键字,最后运行的效果是一样的。
  (对于async和await关键字的使用可以参考,异步爬虫-协程的基本使用这篇文章。)

4.代码生成

  playwright还有一个强大的功能,那就是可以录制我们在浏览器当中的操作并且生成相对应的代码。这个功能可以通过playwright命令行调用codegen实现。比如输入以下命令:

playwright codegen --help

结果如下:
新一代爬取JavaScript渲染页面的利器-playwright(一)_第1张图片
  了解这些后我们可以尝试启动一个Firebox浏览器,然后将操作结果输出到script.py文件中。命令如下:

playwright codegen -o script.py -b firebox

  运行后会弹出一个Firebox浏览器,右侧有个脚本窗口。
新一代爬取JavaScript渲染页面的利器-playwright(一)_第2张图片
新一代爬取JavaScript渲染页面的利器-playwright(一)_第3张图片
  我们在弹出的浏览器打开百度,在搜索框输入nba,然后点击搜索,这时脚本窗口就会生成如下代码。而且我们可以看到会高亮显示我们正在操作的节点。

  在我们操作浏览器的过程中,该窗口的代码会跟着实时变化。所有操作完毕后,关闭浏览器,playwright会生成目标文件,内容如下:

from playwright.sync_api import Playwright, sync_playwright, expect


def run(playwright: Playwright) -> None:
    browser = playwright.firefox.launch(headless=False)
    context = browser.new_context()
    page = context.new_page()
    page.goto("https://www.baidu.com/")
    page.locator("#kw").fill("nba")
    page.get_by_role("button", name="百度一下").click()

    # ---------------------
    context.close()
    browser.close()


with sync_playwright() as playwright:
    run(playwright)


  由此可见,有了代码生成功能,只通过简单的可视化点击操作就能生成代码,可谓非常方便。
  但是,观察生成的代码就会发现,这里的new_page不是通过browser调用的,而是通过context,这个context是由browser调用new_context方法生成的。这里context变量是一个BrowserContext对象,这是一个类似隐身模式的独立上下文环境,其运行资源是单独隔离的。在一些自动化测试中,我们可以为每个测试用例单独创建一个BrowserContext对象,这样可以保障各个测试用例之间互不干扰。

5.支持移动端浏览器

  Playwright另一个特色就是可以支持模拟移动端浏览器,例如模拟打开iphone 13 Pro上的Safari浏览器。

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    iphone_13_pro = p.devices['iPhone 13 Pro']
    browser = p.webkit.launch(headless=False)
    context = browser.new_context(
        **iphone_13_pro,
        locale='zh-CN'
    )
    page = context.new_page()
    page.goto('https://www.whatismybrowser.com/')
    page.wait_for_load_state(state='networkidle')
    page.screenshot(path='browser-iphone.png')
    browser.close()

  运行代码后我们就会发现,弹出一个浏览器窗口,然后加载出了对应页面。
新一代爬取JavaScript渲染页面的利器-playwright(一)_第4张图片
  这里我们先用PlaywrightContextManager对象的devices属性指定了一台移动设备,参数为设备的型号。
  我们创建了一个移动端BrowserContext对象初始化一些设备的信息等,最后把返回的BrowserContext赋值给context变量。
  接着,调用context的new_page方法创建一个新的选项卡,调动wait_for_load_state方法等待页面某个状态完成。netwoidle指网络空闲状态,即当前页面初始化和数据加载完成。

关于页面节点选择器得使用放在下个文章。
新一代爬取JavaScript渲染页面的利器-playwright(二)

你可能感兴趣的:(python,爬虫)