Puppeteer 教程
最后修改于 2023 年 10 月 18 日
在本文中,我们将展示如何使用 puppeteer 库自动化浏览器。
Puppeteer
Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。
Puppeteer 允许在无头模式下使用浏览器(默认模式),无需 UI 即可工作。这对于脚本编写非常有用。
$ npm i puppeteer
我们使用 npm i puppeteer
命令安装 Puppeteer。
Puppeteer 获取内容
在第一个例子中,我们获取页面的内容。
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('http://webcode.me'); const res = await page.content(); console.log(res); await browser.close(); })();
该示例在无头模式下启动浏览器,转到 webcode.me
网页并检索其内容。
const puppeteer = require('puppeteer');
我们加载 puppeteer
库。
const browser = await puppeteer.launch();
当 Puppeteer 通过 launch
或 connect
函数连接到 Chromium 实例时,会创建一个浏览器。 launch
函数接受一组可选参数。 默认情况下,浏览器以无头模式启动。
const page = await browser.newPage();
newPage
函数在默认浏览器上下文中创建一个新页面。
await page.goto('http://webcode.me');
使用 goto
,我们导航到给定的 URL。
const res = await page.content();
content
函数获取页面的完整 HTML 内容,包括 doctype。
await browser.close();
最后,我们关闭浏览器。
Puppeteer 创建屏幕截图
在下一个例子中,我们创建一个网页的屏幕截图。
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('http://webcode.me'); await page.screenshot({ path: 'webcode.png' }); await browser.close(); })();
使用 page.screenshot
函数创建屏幕截图。
Puppeteer 创建 PDF 文件
在下面的例子中,我们从一个网页生成 PDF 文件。
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('http://webcode.me'); await page.pdf({ path: 'webcode.pdf', format: 'a5' }); await browser.close(); })();
该示例使用 page.pdf
函数生成 PDF 文件。我们选择 a5 格式。
Puppeteer 设备模拟
我们可以使用 emulate
函数模拟特定设备。
const puppeteer = require('puppeteer'); (async () => { const options = { headless: false, slowMo: 100 }; const browser = await puppeteer.launch(options); const page = await browser.newPage(); const device = puppeteer.devices['iPhone X']; await page.emulate(device); await page.goto('http://webcode.me'); const res = await page.content() await page.waitForTimeout(5000); console.log(res); await browser.close() })();
在示例中,我们模拟 iPhone 设备。
const options = { headless: false, slowMo: 100 }; const browser = await puppeteer.launch(options);
我们向 launch
函数传递一些选项。我们关闭无头模式并稍微放慢自动化速度。
const device = puppeteer.devices['iPhone X']; await page.emulate(device);
我们选择一个设备并进行模拟。
const res = await page.content() await page.waitForTimeout(5000); console.log(res);
在我们输出网页内容之前,我们使用 waitForTimeout
暂停脚本的执行;休眠时间以毫秒为单位给出。
Puppeteer 链接点击
click
函数使用给定的选择器获取一个元素,如果需要,将其滚动到视图中,然后使用 page.mouse
在元素的中心单击。
const puppeteer = require('puppeteer'); const run = async () => { const options = { headless: false }; const browser = await puppeteer.launch(options); const page = await browser.newPage(); await page.goto('http://example.com'); await page.waitForTimeout(3000); console.log(`Current page: ${page.url()}`); await page.click('a'); console.log(`Current page: ${page.url()}`); await page.waitForTimeout(3000); return browser.close(); }; const logErrorAndExit = err => { console.log(err); process.exit(); }; run().catch(logErrorAndExit);
在示例中,我们导航到 example.com
页面,等待三秒钟,然后单击可用的链接。
Puppeteer 提交表单
在下面的例子中,我们提交一个 HTML 表单。我们使用 Express 库创建一个简单的 Web 应用程序。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Form</title> </head> <body> <form action="message" method="post"> <div> <label>Name:</label> <input type="text" name="name"> </div> <div> <label>Message</label> <input type="text" name="message"> </div> <button type="submit">Send</button> </form> </body> </html>
该表单包含两个输入框:姓名和消息。
const express = require('express'); const path = require('path'); const app = express(); app.use(express.static('public')); app.use(express.urlencoded({ extended: true })); app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'index.html')); }); app.post('/message', (req, res) => { res.set({ 'Content-Type': 'text/plain; charset=utf-8' }); let name = req.body.name; let message = req.body.message; let output = `${name} says: ${message}`; res.send(output); }); app.listen(3000, () => { console.log('Application started on port 3000'); })
这个 Express 应用程序处理提交的表单。它根据发送的参数构建消息。
const puppeteer = require('puppeteer'); (async () => { const options = { headless: false, slowMo: 40 }; const browser = await puppeteer.launch(options); const page = await browser.newPage(); await page.goto('https://:3000'); await page.type('input[name="name"]', 'John Doe'); await page.type('input[name="message"]', 'Hello there!'); await page.click('button[type=submit]'); const content = await page.content(); if (content.includes('John Doe says: Hello there!')) { console.log('form submitted OK'); } else { console.log('failed to submit form'); } await browser.close(); })();
在示例中,我们填写表单,提交它并验证响应。
const options = { headless: false, slowMo: 40 };
我们在 UI 模式下运行该示例;放慢一点。
await page.type('input[name="name"]', 'John Doe'); await page.type('input[name="message"]', 'Hello there!');
使用 page.type
函数,我们将数据填入输入标签。
await page.click('button[type=submit]');
我们使用 page.click
提交表单。
const content = await page.content(); if (content.includes('John Doe says: Hello there!')) { console.log('form submitted OK'); } else { console.log('failed to submit form'); }
我们验证来自 Express 应用程序的响应。
Puppeteer DuckDuckGo 搜索
在下面的例子中,我们将一个术语传递给 DuckDuckGo 搜索引擎并处理结果。
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://duckduckgo.com/', { waitUntil: 'networkidle2' }); await page.type("input[id=search_form_input_homepage]", "falcon"); await Promise.all([ page.click('input[type="submit"]'), page.waitForNavigation() ]); const res = await page.evaluate(() => [...document.querySelectorAll(".result__snippet.js-result-snippet")].map(e => ({ text: e.innerText }))); for (let e of res) { console.log(e.text); } await browser.close(); })();
该示例搜索 falcon 术语并返回 DuckDuckGo 的顶部定义。
await page.goto('https://duckduckgo.com/', { waitUntil: 'networkidle2' });
我们导航到 DuckDuckGo;通过将 waitUntil
选项设置为 networkidle2
,我们认为导航完成,当网络连接不超过 2 个且持续至少 500 毫秒时。 这确保我们正确加载了页面,并且可以找到搜索框。
await page.type("input[id=search_form_input_homepage]", "falcon");
我们在 DuckDuckGo 的搜索框中输入 falcon 术语。
await Promise.all([ page.click('input[type="submit"]'), page.waitForNavigation() ]);
我们提交表单并等待结果。
const res = await page.evaluate(() => [...document.querySelectorAll(".result__snippet.js-result-snippet")].map(e => ({ text: e.innerText })));
我们在页面上下文中评估匿名函数。 在该函数中,我们选择同时具有 result__snippet
和 js-result-snippet
类的所有标签。 这是 DuckDuckGo 存储其定义的地方。
for (let e of res) { console.log(e.text); }
我们遍历定义并将它们打印到控制台。
来源
在本文中,我们使用 puppeteer 库自动化浏览器。