网页抓取教程之Playwright篇

2021-11-10 14:57:22 浏览数 (1)

Playwright网页抓取教程

近年来,随着互联网行业的发展,互联网的影响力逐渐上升。这也归功于技术水平的提高,研发出了越来越多用户体验良好的应用程序。此外,从网络应用程序的开发到测试,自动化在整个过程中的使用也越来越普及。网络爬虫工具越发流行。

拥有高效的工具来测试网络应用程序至关重要。Playwright等库在浏览器中打开网络应用程序并通过其他交互,例如单击元素、键入文本,以及从网络中提取公共数据来加速整个过程。

本教程会解释有关Playwright的相关内容,以及如何将其用于自动化甚至网络抓取。

什么是Playwright?

Playwright是一个测试和自动化框架,可以实现网络浏览器的自动化交互。简而言之,您可以编写打开浏览器的代码,用代码实现使用所有网络浏览器的功能。自动化脚本可以实现导航到URL、输入文本、单击按钮和提取文本等功能。Playwright最令人惊喜的功能是它可以同时处理多个页面且不用等待,也不会被封锁。

Playwright支持大多数浏览器,例如Google Chrome、Firefox、使用Chromium内核的Microsoft Edge和使用WebKit内核的Safari。跨浏览器的网络自动化是Playwright的强项,可以为所有浏览器有效地执行相同的代码。此外,Playwright支持各种编程语言,例如Node.js、Python、Java和.NET。您可以编写代码用于打开网站并使用这些语言中的任何一种与之交互。

Playwright的文档内容非常详细,覆盖面广。它涵盖了从入门到高级的所有类和方法。

支持Playwright的代理

Playwright支持使用代理。我们将以下面的Node.js和Python的代码片段作引,逐步教您如何在Chromium中使用代理:

Node.js:

代码语言:javascript复制
const { chromium } = require('playwright'); "
const browser = await chromium.launch();

Python:

代码语言:javascript复制
from playwright.async_api import async_playwright
import asyncio
with async_playwright() as p:
browser = await p.chromium.launch()

以上代码只需要稍作修改即可集成代理。在使用Node.js时,启动函数可以接受LauchOptions类型的可选参数。这个LaunchOption对象又可以发送其他几个参数,例如,headless。需要的另一个参数是proxy.这个代理是具有这些属性的另一个对象:serverusernamepassword等。第一步是创建可以指定这些参数的对象。

代码语言:javascript复制
// Node.js
const launchOptions = {
     proxy: {
     server: 123.123.123.123:80'
     },
     headless: false
}

第二步是将此对象传递给启动函数:

代码语言:javascript复制
const browser = await chromium.launch(launchOptions);

就Python而言,情况略有不同。无需创建LaunchOptions。相反,所有值都可以作为单独的参数发送。以下是代理字典的发送方式:

代码语言:javascript复制
# Python
proxy_to_use = {
        'server': '123.123.123.123:80'
}
browser = await pw.chromium.launch(proxy=proxy_to_use, headless=False)

在决定使用哪种代理来执行抓取时,您最好使用住宅代理,因为它们不会留下痕迹,也不会触发任何安全警报。Oxylabs的住宅代理是一个覆盖地区广且稳定的代理网络。您可以通过Oxylabs的住宅代理访问特定国家、省份甚至城市的站点。最重要的是,您还可以将Oxylabs的代理与Playwright轻松集成。

01.使用Playwright进行基本抓取

下面我们将介绍如何通过Node.js和Python使用Playwright。

如果您使用的是Node.js,需要创建一个新项目并安装Playwright库。可以使用这两个简单的命令来完成:

代码语言:javascript复制
npm init -y
npm install playwright

打开动态页面的基本脚本如下:

代码语言:javascript复制
const playwright = require('playwright');
(async () => {
        const browser = await playwright.chromium.launch({
        headless: false // Show the browser.
});

        const page = await browser.newPage();
        await page.goto('https://books.toscrape.com/');
        await page.waitForTimeout(1000); // wait for 1 seconds
        await browser.close();
})();

让我们看一下以上代码。代码的第一行导入了Playwright。然后,启动了一个Chromium实例。它允许脚本自动化Chromium。请注意,这个脚本会以可视化的用户界面运行。成功传递headless:false后,打开一个新的浏览器页面,page.goto函数会导航到Books to Scrape这个网页。再等待1秒钟向最终用户显示页面。最后,浏览器关闭。

同样的代码用Python编写也很简单。首先,使用pip命令安装Playwright:

代码语言:javascript复制
pip install playwright

请注意,Playwright支持两种方式——同步和异步。以下示例使用异步API:

代码语言:javascript复制
from playwright.async_api import async_playwright
import asyncio

async def main():
    async with async_playwright() as pw:
    browser = await pw.chromium.launch(
        headless=False  # Show the browser
    )
    page = await browser.new_page()
    await page.goto('https://books.toscrape.com/')
    # Data Extraction Code Here
    await page.wait_for_timeout(1000)  # Wait for 1 second
    await browser.close()
if __name__ == '__main__':
    asyncio.run(main())

此代码类似于Node.js代码。最大的区别在于asyncio库的使用。另一个区别是函数名称从camelCase变为snake_case

如果您想创建多个浏览器环境,或者想要更精确的控制,您可以创建一个环境对象并在该环境中创建多个页面。该代码将会在新选项卡中打开页面:

代码语言:javascript复制
const context = await browser.newContext();
const page1 = await context.newPage();
const page2 = await context.newPage();

如果您还想在代码中处理页面上下文。可以使用page.context()函数获取浏览器页面上下文。

02.定位元素

要从某元素中提取信息或单击某元素,第一步是定位该元素。Playwright支持CSS和XPath两种选择器。

通过一个实际的例子可以更好地理解这一点。在Chrome中打开待爬取页面网址,并右键单击第一本书并选择查看源代码。

您可以看到所有的书都在article元素下,该元素有一个类product_prod。

要选择所有书籍,您需要对所有article元素设置一个循环。article元素可以使用CSS选择器进行选择:

代码语言:javascript复制
.product_pod

同样,也可以使用XPath选择器:

代码语言:javascript复制
//*[@class="product_pod"]

要使用这些选择器,最常用的功能如下:

$eval(selector, function)–选择第一个元素,将元素发送给函数,返回函数的结果;

$$eval(selector, function)–同上,不同的是它选择了所有元素;

querySelector(selector)–返回第一个元素;

querySelectorAll(selector)–返回所有元素。

这些方法在CSS和XPath选择器中都能正常工作。

03.抓取文本

继续以Books to Scrape页面为例,在页面加载后,您可以使用选择器和$$eval函数提取所有书籍容器。

代码语言:javascript复制
const books = await page.$$eval('.product_pod', all_items
 => {
// run a loop here
})

然后可以在循环中提取包含书籍数据的所有元素:

代码语言:javascript复制
all_items.forEach(book => {
        const name = book.querySelector('h3').innerText;
})

最后,innerText属性可用于从每个数据点中提取数据。以下是Node.js中的完整代码:

代码语言:javascript复制
const playwright = require('playwright');
(async () => {
       const browser = await playwright.chromium.launch();
       const page = await browser.newPage();
       await page.goto('https://books.toscrape.com/');
       const books = await page.$$eval('.product_pod', all_items 
=> {
     const data = [];
     all_items.forEach(book => {
             const name = book.querySelector('h3').innerText;
             const price = book.querySelector('.price_color').
innerText;
              const stock = book.querySelector('.availability').
innerText;
              data.push({ name, price, stock});
     });
     return data;
     });
     console.log(books);
     await browser.close();
})();

Python中的代码则会有些不同。Python有一个函数eval_on_selector,和Node.js的$eval类似,但是不适合这种场景。原因是第二个参数仍需是JavaScript。在某种情况下使用JavaScript可能很好,但在这种情况下,用Python编写整个代码会更加适用。

最好使用query_selectorquery_selector_all分别返回一个元素和一个元素列表。

代码语言:javascript复制
from playwright.async_api import async_playwright
import asyncio

async def main():
      async with async_playwright() as pw:
      browser = await pw.chromium.
      page = await browser.new_page()
      await page.goto('https://books.toscrape.com')

      all_items = await page.query_selector_all('.product_pod')
      books = []
      for item in all_items:
         book = {}
         name_el = await item.query_selector('h3')
         book['name'] = await name_el.inner_text()
         price_el = await item.query_selector('.price_color')
         book['price'] = await price_el.inner_text()
         stock_el = await item.query_selector('.availability')
         book['stock'] = await stock_el.inner_text()
         books.append(book)
      print(books)
      await browser.close()

if __name__ == '__main__':
      asyncio.run(main())

最后,Node.js和Python代码的输出结果是相同的。

Playwright VS Puppeteer和Selenium

抓取数据时,除了使用Playwright,您还可以使用Selenium和Puppeteer。

对于Puppeteer,您能使用的浏览器和编程语言十分有限。目前唯一可以使用的语言是JavaScript,唯一可以兼容的浏览器是Chromium。

对于Selenium,虽然对浏览器语言的兼容性不错。但是,它速度慢且对开发人员不太友好。

另外需要说明的是,Playwright可以拦截网络请求。请参阅有关网络请求的更多详细信息。

下面为大家整理了三个工具的对比:

_

Playwright

Puppeteer

Selenium

速度

较慢

归档能力

优秀

优秀

普通

开发体验

最好

普通

编程语言

JavaScript、Python、C#和Java

JavaScript

Java、Python、C#、Ruby、JavaScript和Kotlin

支持方

微软

谷歌

社区和赞助商

社区

小而活跃

大而活跃

大而活跃

可用的浏览器

Chromium、Firefox和WebKit

Chromium

Chrome、Firefox、IE、Edge、Opera和Safari等

结论

本文探讨了Playwright作为测试工具抓取动态站点的的功能,还介绍了Node.js和Python中的代码示例。由于Playwright的异步特性和跨浏览器支持,它是其他工具较为流行的替代方案。

Playwright可以实现导航到URL、输入文本、单击按钮和提取文本等功能。它可以提取动态呈现的文本。这些事情也可以通过Puppeteer和Selenium等其他工具来完成,但是如果您需要使用多个浏览器,或者您需要使用JavaScript/Node.js以外的语言,那么Playwright将是一个更好的选择。

如果您对其他类似主题感兴趣,请查看我们关于使用Selenium进行网络抓取的文章或查看Puppeteer教程。您也可以随时访问我们的网站查看相关内容。

0 人点赞