Bootstrap

playwright爬虫,TypeScriptr入门

1. 爬虫与playwright

网页爬虫并不是一个新概念。在JavaScript生态系统中,CheerioSeleniumPuppeteerPlaywright等工具都帮助简化了网页爬虫的过程。作为一个较新的网页爬虫库,Playwright具有以下几个吸引人的特点:

1.1 强大的定位器(Locators)

Playwright使用定位器来选择网页上的元素,这些定位器具有内置的自动等待和重试逻辑。自动等待逻辑简化了您的爬虫代码,因为您不必手动等待网页加载完成。

此外,重试逻辑使Playwright成为抓取现代单页应用 (SPA)的理想库,这些应用在初始页面加载后会动态加载数据。

示例代码:

const { chromium }=require('playwright');

(async ()=>{
const browser = await chromium.launch();
const page = await browser.newPage();
  await page.goto('https://example.com');

// 使用定位器选择元素
const element = await page.locator('text="Example Domain"').first();
  console.log(await element.textContent());

  await browser.close();
})();

1.2 多种定位器方法

使用定位器时,Playwright允许您使用多种不同的语法来指定要在网页上定位的元素,包括CSS选择器语法、XPath语法和元素文本内容。还可以对定位器应用过滤器,以进一步细化定位器的范围。

示例代码:

// CSS选择器
const cssLocator = page.locator('div.classname');

// XPath语法
const xpathLocator = page.locator('//div[@class="classname"]');

// 元素文本内容
const textLocator = page.locator('text="Example Domain"');

// 过滤器
const filteredLocator = page.locator('div.classname').filter({ hasText: 'specific text' });

1.3 Playwright的其他优势

自动处理等待

Playwright内置的智能等待机制可以自动处理网络延迟和动态内容加载问题,使爬虫代码更加简洁和可靠。

跨浏览器支持

Playwright支持在多个浏览器(如ChromiumFirefoxWebKit)上运行,从而确保爬取的数据具有一致性。

无头模式

Playwright可以在无头模式下运行,减少资源消耗,提高爬取效率。

2. 使用Playwright进行网页爬虫

下面将创建一个Node.js项目,安装Playwright,并学习如何使用Playwright定位、交互和提取网页数据。

2.1 前置条件

本文中的代码示例在最新的长期支持版本(LTS)Node.js上运行,截至撰写本文时,该版本为v18.15.0。请确保在开始之前已安装Node.js

推荐使用能够突出显示JavaScript语法并具备自动完成功能的代码编辑器,例如Visual Studio Code

2.2 创建一个新项目

打开一个新的终端窗口,为Node.js项目创建一个新文件夹并进入该文件夹:

mkdir playwright-demo
cd playwright-demo

接下来,通过运行以下npm命令创建的Node.js项目:

npm init -y

2.3 安装Playwright

创建Node.js项目后,在终端窗口中使用以下命令安装Playwright库:

npm install playwright

该库可能需要一些时间来安装,因为Playwright在安装过程中会下载必要的浏览器。

2.4 打开主页

安装Playwright库后,在项目文件夹中创建一个名为index.js的新文件。然后将以下代码复制到其中:

const playwright =require("playwright");

(async ()=>{
const browser = await playwright.chromium.launch({
    headless:false,
});
const context = await browser.newContext();
const page = await context.newPage();

  await page.goto("https://brightdata.com/");
  await page.waitForTimeout(10000);

  await browser.close();
})();

使用以下命令在终端中运行代码片段:

node index.js

应该会打开一个Chromium浏览器并加载Bright Data主页。

 

2.5 定位元素

现在已经使用Playwright导航到Bright Data的主页,可以使用定位器来选择网页上的特定元素。Playwright有多种定位器,以下部分将演示每种定位器的工作原理。

使用CSS选择器定位元素

Playwright允许您使用CSS选择器在网页上定位元素,这是一种在CSS中用于应用样式到特定HTML元素的简洁而强大的语法。

例如,Bright Data的徽标是页面头部的一个<svg>元素,并且附加了page_header_logo_svg类:

const logoSvg = page.locator(".page_header_logo_svg");

使用XPath查询定位元素

XPath是另一种可以用来定位XML文档中元素的选择器语法。由于HTMLXML,可以使用该语法在网页上查找HTML元素。

例如,可以使用以下XPath查询选择与上一节中相同的SVG徽标:

const logoSvg = page.locator("//*[@class='page_header_logo_svg']");

按角色定位元素

HTML元素可以具有不同的角色,这些角色为网页提供语义意义,使屏幕阅读器和其他工具更容易支持该网页。您可以阅读更多关于角色的信息这里。

以下代码片段演示了如何使用角色和名称找到Start free trial按钮:

const signupButton = page.getByRole("button", {
  name: "Start free trial",
});

按文本定位元素

如果HTML元素没有有意义的标识符属性,例如idclass属性,可以使用getByText方法按文本选择元素。

例如,Bright Data主页的英雄部分有一个标题,其中包含蓝色的structured data字样:

const structuredData = page.getByText("structured data");

按标签定位元素

HTML表单中,输入元素通常有标签。Playwright可以使用这些标签来识别与该标签关联的输入元素,使用getByLabel方法。

例如,Bright Data登录页面有一个包含Work email字样的输入元素:

await page.goto("https://brightdata.com/cp/start");
const emailInput = page.getByLabel("Work email");

按占位符定位元素

还可以根据显示的占位符值定位输入元素,使用getByPlaceholder方法。

await page.goto("https://brightdata.com/cp/start");
const emailInput = page.getByPlaceholder("[email protected]");

alt文本定位元素

HTML允许使用alt属性为图像添加文本描述,如果图片未加载,该描述会显示出来,并由屏幕阅读器读取以描述图像。PlaywrightgetByAltText方法允许使用alt属性定位img元素。

例如,Bright Data列出了使用其数据的行业。可以使用althealthcare use case检索用于医疗行业的图像:

const healthcareImage = page.getByAltText("healthcare use case");

按标题定位元素

最后一个Playwright选择器是getByTitle方法,它通过title属性定位HTML元素。当用指针悬停在HTML组件上时,会看到title值。 例如,Bright Data帮助台网站包含一个具有title属性的登录链接:

await page.goto("https://help.brightdata.com/hc/en-us");
const signInLink = page.getByTitle("Opens a dialog");

2.6 与元素交互

定位网页上的元素后,可以与之交互。例如,可能需要登录网站才能抓取受保护的页面。

以下代码片段演示了不同的Playwright方法来与网页上的元素交互。代码中的每个函数都有相应的解释:

const playwright =require("playwright");

(async ()=>{
const browser = await playwright.chromium.launch({
    headless:false,
});
const context = await browser.newContext();
const page = await context.newPage();

  await page.goto("https://brightdata.com/");

  await page.locator("#hero_new").getByRole("button",{ name:"Start free trial"}).click();
  await page.locator(".hs_firstname input").fill("John");
  await page.locator(".hs_lastname input").fill("Smith");
  await page.locator(".hs_email input").type("[email protected]");
  await page.locator(".hs_numemployees select").selectOption("1-9 employees");
  await page.locator(".legal-consent-container input").check();

  await page.waitForTimeout(10000);
  await browser.close();
})();

点击元素

在上面的代码片段中,Playwright首先点击了Start free trial按钮,以便显示对话框:

await page.getByRole("button", { name: "Start free trial" }).click();

填充文本字段

示例中,代码片段使用两种方法填充注册表单上的文本字段:

await page.locator(".hs_firstname input").fill("John");
await page.locator(".hs_lastname input").fill("Smith");
await page.locator(".hs_email input").type("[email protected]");

选择下拉选项

注册表单有一个下拉字段,用于选择公司规模,Playwright将其填充为1–9 employees

await page.locator(".hs_numemployees select").selectOption("1-9 employees");

勾选复选框和单选按钮

在提交表单之前,您需要接受条款和条件。以下代码片段选中了相应的复选框:

await page.locator(".legal-consent-container input").check();

从元素中提取数据

数据提取是网页爬虫的关键。Playwright允许您使用多种方法从定位到的元素中检索不同类型的数据。以下部分介绍了其中的一些方法。

提取内部文本

innerText方法允许您提取元素内部的文本。例如,Bright Data有一个标题:

const headerText = await page.locator(".brd_hero__title.h1").innerText();

提取内部HTML

Playwright还允许您使用innerHTML方法提取元素的内部HTML。例如,可以获取Bright Data页脚的HTML

const footerHtml = await page.locator("#footer").innerHTML();

提取属性值

可能需要从HTML元素的属性中提取数据,例如链接的href属性。以下Playwright代码片段演示了如何抓取登录链接的href属性:

const signUpHref = await page.getByText("Log in").getAttribute("href");

截图页面

在抓取数据时,可能需要截取屏幕截图以进行审核。可以使用screenshot`方法来执行此操作。该函数允许配置多个选项,例如保存截图文件的位置以及是否截取整个页面的截图。

以下代码片段截取了Bright Data全页面截图并保存:

await page.screenshot({
  path: "homepage.png",
  fullPage: true,
});

通过上述步骤和示例,可以使用Playwright有效地进行网页爬虫,定位和提取网页上的数据。

小结论

详细介绍了如何使用Playwright进行网页爬虫,包括环境配置、编写脚本、元素交互,元素内容提取等。Playwright强大的功能和灵活的API,使其成为网页爬虫的理想工具,帮助你高效地从网页中提取所需数据,提升数据采集的效率和质量。

Python到TypeScript的快速入门

对于熟悉Python的测试人员和开发人员来说,初次学习使用TypeScript可能并不需要花费太多时间

3. TypeScript语法基础

3.1 变量和类型

Python中,变量声明是动态的,而在TypeScript中,我们需要显式声明变量类型。

Python:

name = "Alice"
age = 30

TypeScript:

let name: string = "Alice";
let age: number = 30;

3.2 异步代码

Python中,我们使用asyncawait来处理异步代码,TypeScript中也是如此。

Python:

async def fetch_data():
    data = await fetch('https://api.example.com')
    return data

TypeScript:

async function fetchData(): Promise<any> {
  const response = await fetch('https://api.example.com');
  const data = await response.json();
  return data;
}

3.3 类和函数

TypeScriptPython类似,支持面向对象编程。

Python:

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return f"{self.name} says hello!"

dog = Animal("Dog")
print(dog.speak())

TypeScript:

class Animal {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  speak(): string {
    return `${this.name} says hello!`;
  }
}

const dog = new Animal("Dog");
console.log(dog.speak());

4. Playwright入门

4.1 Playwright安装配置

在项目中安装 ·Playwright· 后,创建一个新的测试文件 test.ts

4.2 基本语法

import { chromium, Browser, Page } from 'playwright';

(async () => {
  const browser: Browser = await chromium.launch({ headless: false });
  const page: Page = await browser.newPage();
  await page.goto('https://example.com');
  const title: string = await page.title();
  console.log(`页面标题是: ${title}`);
  await browser.close();
})();

4.3 运行测试脚本

在终端中运行以下命令编译并执行 TypeScript 脚本:

npx ts-node test.ts

5. Playwright进阶

5.1 Hooks钩子

Playwright 提供了钩子函数,可以在测试执行的不同阶段执行特定操作。常见的钩子函数有

beforeAll()

在所有的test()执行之前运行1次,且只运行1次。

beforeEach()

在每一个test()执行之前运行1次,运行总次数取决于多少个test()

afterAll()

在所有的test()执行之后运行1次,且只运行1次。

afterEach()

在每一个test()执行之后运行1次,运行总次数取决于多少个test()

示例如下:

import { chromium, Browser, Page } from 'playwright';

let browser: Browser;
let page: Page;

beforeAll(async () => {
  browser = await chromium.launch();
  page = await browser.newPage();
});

afterAll(async () => {
  await browser.close();
});

beforeEach(async () => {
  await page.goto('https://example.com');
});

afterEach(async () => {
  // 清理代码
});

5.2 断言(Assertions)

使用 Playwright 的内置断言库,可以方便地验证测试结果,这部分对于使用Python还是Typescript来说区别并不大。示例如下

import { test, expect } from '@playwright/test';

test('has title', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveTitle('Example Domain');
});

test('get started link', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  const getStarted = page.locator('text=Get Started');
  await expect(getStarted).toHaveAttribute('href', '/docs/intro');
});

总结

通过这篇教程,相信你对 TypeScript 的基本语法有了一个初步了解,结合Playwright提供的钩子和断言,完全可以开始自动化测试脚本编写。进阶和高级的Playwright用法可以参考官网

 

;