playwright 的使用

3,053 阅读2分钟

playwright官方文档

你需要了解Promise、async/await 的一些知识, 此文章使用yarn, 你也可以使用npm。
yarn add -D playwright // 会自动下载相对应的浏览器二进制文件
yarn add -D playwright-cli // 可用于记录操作,自动生成代码。
yarn add -D jest jest-playwright-preset // 编写测试使用, 可以忽略

基本使用:

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

(async function test () {
    // 开启并设置浏览器
    const browser = await chromium.launch({
        headless: false,
        devtools: true,
        slowMo: 200
    });

    // 新创建一个标签页
    const page = await browser.newPage();

    // 页面跳转
    await page.goto('https://www.baidu.com');

    // 在浏览器的上下文中执行某个函数
    await page.evaluate(() => console.log('test-start'));
    // 选取input元素, 并输入值
    await page.fill('input#kw', 'playwright-npm');

    // 等待1.5s
    await page.waitForTimeout(1500);

    // 可传入可以被序列化的参数, #! Function对象不能传递. 不知道从何时起alert不会再阻塞浏览器
    await page.evaluate((date) => console.log('test:', date), new Date());
    await page.waitForTimeout(5000);

    // 关闭页面以及浏览器
    await page.close();
    await browser.close();
})();

如果出错, 请将 await browser替换成await (await browser)尝试一下。

下面来写一个使用谷歌翻译的IIFE函数

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

(async function translate (rawData) {
    const inSelector = `div > textarea.er8xn`;
    const outSelector = `div.J0lOec > span.VIiyi > span > span`;

    // 开启并设置浏览器
    const browser = await chromium.launch({
        headless: false,
        slowMo: 200
    });

    // 新创建一个标签页
    const page = await browser.newPage();

    // 页面跳转
    await page.goto('https://translate.google.cn/', {
        waitForTimeout: 60000,
        waitUntil: 'domcontentloaded'
    });

    // 等待元素
    const stdIN = await page.waitForSelector(inSelector, {
        state: 'attached'
    });

    // 输入测试数据
    await stdIN.fill('test');

    // 等待显示翻译结果的元素
    let stdOUT = await page.waitForSelector(outSelector, {
        timeout: 1500
    });

    // 声明变量
    let preVal;
    let outVal = await stdOUT.innerText();

    if (outVal !== '测试') {
        await page.waitForTimeout(1000);
        // 获取最新的值
        outVal = await page.$eval(outSelector, e => e.innerText);

        if (outVal !== '测试') {
            throw new Error('链接失败,请重新尝试。');
        }
    } else {
        console.log('链接成功');
        preVal = outVal;
    }

    let translateData = [];
    // 进行翻译,此处不用map or forEach 使用其他数组API 请慎重
    for (const item of Object.values(rawData)) {
        await stdIN.fill(item);

        // 缓和时间。 缓和时间与网速度有关
        await page.waitForTimeout(1500);

        // 获取最新的值
        let outData = await page.$eval(outSelector, e => e.innerText);
        console.log(preVal, outData, 'gap--');
        await page.waitForTimeout(1000);
        if (preVal === outData) {
            // 最大缓和时间
            await page.waitForTimeout(1000);
            outData = await stdOUT.innerText();
        }

        preVal = outData;

        translateData.push({
            item,
            outData
        });
    }

    // 关闭页面以及浏览器
    await page.close();
    await browser.close();
    console.log('close---', translateData);
    return translateData;
})(['python', 'good', 'left', 'right', 'attachment']).catch(() =>
    console.log('err')
);

就这样吧,其实还是由很大的优化空间,此文章只是做个简单的介绍,官方文档也一直在更新, 与我刚接触时的API已经变了不少, 高级技巧请到官方文档学习哟!