Puppeteer:什么是 Puppeteer,为什么在网络搜刮中需要它?
从网站收集信息需要方便可靠的工具。其中,Puppeteer 是一个用于 Node.js 的库。js 的库,它允许您模拟真实用户的操作:打开页面、点击元素、填写表格甚至截图 - 所有操作均为全自动模式。使用 Puppeteer 进行网页刮擦变得更加容易,尤其是涉及使用 JavaScript 加载内容的动态网站时。Puppeteer 不仅能 "看到 "用户所看到的内容,还能让您与这些内容进行更深层次的交互,因此非常适合数据收集、网站测试和任何复杂任务的自动化。如果您使用的是 JavaScript 和 TypeScript,那么 Puppeteer 将是您进行 Web 搜索和许多其他任务的最佳选择!
! 对于Python语言,还有一个非官方的类似工具——Pyppeteer。 |
Puppeteer的好处
使其如此受欢迎的主要优点:
常见的搜索工具(如 Axios、Cheer 等)。例如 Axios、Cheerio)在处理使用 JavaScript 动态加载内容的网站时经常会遇到困难。而 Puppeteer 在这方面做得很好!它运行一个成熟的浏览器(谷歌 Chrome 浏览器或火狐浏览器),允许你像真正的用户一样加载页面。这意味着所有内容,甚至是脚本执行后出现的内容,都可用于分析和数据收集。
Easily interact with the DOM - add or remove elements, click buttons, fill out forms, scroll pages, and more.
Puppeteer 允许您在正常模式和无头模式(无图形用户界面)下控制浏览器。
无头模式 - 实现快速、谨慎自动化的理想选择:浏览器在 "后台 "运行,节省资源并加快任务执行速度。
完整浏览器模式 - 对于调试和开发非常有用:您可以直观地观察页面上发生的情况。
Puppeteer 还可以通过更改用户代理标头来模拟设备,这有助于绕过封锁和限制网站。您甚至可以模拟 3G 或 Wi-Fi 等网络模式来测试页面性能。
您可以拍摄页面快照或将其保存为 PDF 文件。这对于创建报告、记录网页内容或测试非常有用。
我们将在下文中详细讨论所有这些优势。
所以说,Puppeteer 不仅仅是一个刮擦工具,而且是任何浏览器自动化相关任务的通用助手。
Puppeteer
- 该库的安装非常简单。首先,确保您已安装 Node.js ( 官方网站).
- 然后打开终端或命令提示符并运行 npm 命令:
npm i puppeteer
此命令会自动下载最新版本的 Chromium。如果 Chromium 已安装或您想使用其他浏览器,则可以不安装 Chromium 而直接安装 Puppeteer:
npm i puppeteer-core
与DOM和用户操作的互动
Puppeteer 为您的网页自动化提供了广泛的功能。它不仅允许您通过操作 DOM(Document Object Model杂项 DOM 操作
Puppeteer 允许:
- 添加或删除元素。 使用方法 evaluate() 在页面上下文中执行 JavaScript 代码。
等待 page.evaluate(() => {
const newElement = document.createElement('div');
newElement.textContent = 'New element!';
document.body.appendChild(newElement); // 向 DOM 添加元素
});
- 更改页面内容。 您可以轻松更改元素的文本、属性或样式:
等待 page.evaluate(() => {
document.querySelector('h1').textContent = 'Updated header';
});
省略用户操作
Puppeteer 可以模拟用户操作,这对于测试和从交互式网站中刮取数据特别有用。
等待页面。click('button#submit'); // 点击 id 为 "submit "的按钮
await page.evaluate(() => window.scrollBy(0, 1000)); // 向下滚动
等待页面。type('input[name="username"]', 'myUsername'); // 在字段中输入文本
await page.type('input[name="password"]', 'myPassword');
await page.click('button[type="submit"]'); // 提交表单
- 自动导航。 Puppeteer 可以在页面之间导航、跟踪加载并与新元素交互:
await page.goto('https://example.com');
await page.waitForSelector('h1'); // 等待页眉出现
使用动态网站
许多现代网站使用 JavaScript 异步加载内容。Puppeteer 可轻松处理此类任务:
等待页面。waitForSelector('.dynamic-element');
- 使用异步加载的元素。 在刮擦数据时,正确处理稍后出现的元素非常重要。 return document.querySelector('.loaded-content') !== null; });
使用Puppeteer进行网页抓取的参数
要使用 Puppeteer 高效、正确地进行网络刮擦,您需要考虑各种参数和设置,它们将有助于提高过程的性能、准确性和稳定性。让我们来看看可在项目中使用的关键参数:
- Headless-mode. Puppeteer 可以在无头(无界面)或有头(有界面)模式下运行。
const browser = await puppeteer.launch({ headless: true }); // Default true
const browser = await puppeteer.启动({
args: ['--window-size=1920,1080']
});
const page = await browser.newPage();
await page.setViewport({ width: 1920, height: 1080 });
- Change User-Agent (有助于避免阻塞和模仿不同的设备):
等待页面。setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36');
await page.waitForSelector('.dynamic-element', { visible: true });
- Waiting Navigation (用于跟踪页面之间的转换):
等待 Promise。all([
page.click('a#next-page') // 点击并等待导航
]);
const browser = await puppeteer.启动({
args:['--disable-gpu','--no-sandbox']。
});
const iPhone = puppeteer.devices['iPhone X'];
await page.emulate(iPhone);
const browser = await puppeteer.launch({
args:['--proxy-server=your-proxy-address']。
});
const cookies = [{ name: 'session', value: 'abc123', domain: 'example.com' }];
await page.setCookie(....cookies);
- 绕过反僵尸系统 (Puppeteer-extra 和插件有助于绕过自动化保护):
npm install puppeteer-extra puppeteer-extra-plugin-stealth
const puppeteer = require('puppeteer-extra');
const stealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(stealthPlugin());
数据收集和变化监测参数:
const title = await page.$eval('h1', element => element.textContent);
- 要跟踪更改,请使用 MutationObserver(嵌入在浏览器中的 JavaScript 对象,允许您跟踪 DOM 中的变化并做出反应,例如添加或删除元素、更改属性或文档结构):
await page.exposeFunction('onMutation', (mutations) => {
console.log('DOM 已更改:', mutations);
});
await page.evaluate(() => {
const observer = new MutationObserver((mutations) => {
window.onMutation(mutations);
});
observer.observe(document.body, { childList: true, subtree: true });
});
Web Scraping 代码示例
现在,应用 Puppeteer 的基本参数知识,尤其是在网络刮擦的背景下,让我们创建一个简单的代码示例,在测试网站上演示所有上述功能的操作 Books to Scrape.让我们尝试获取有关书籍的信息:
const puppeteer = require('puppeteer');
(async () => {
// 使用附加参数启动浏览器,以进行优化和仿真
const browser = await puppeteer.launch({
无头:false, // 使用界面打开浏览器
args:['--no-sandbox'], // 附加参数以提高 性能
defaultViewport:{设置浏览器窗口大小
宽度:1280、
height:800。
}
});
const page = await browser.newPage();
// 安装用户代理(浏览器模拟)
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36');
;
// 转到登陆页面
await page.goto('https://books.toscrape.com/', { waitUntil: 'networkidle2' }); // 等待页面完全加载
// 等待加载页面上的元素
await page.waitForSelector('ol.row li');
;
// 仅检索并输出书名
const bookTitles = await page.evaluate(() => {
const bookElements = document.querySelectorAll('ol.row li h3 a');
return Array.from(bookElements).map(book => book.getAttribute('title') || 'No title');
});
// 用列表编号输出每个名称
console.log('Book titles:');
bookTitles.forEach((title, index) => console.log(`${index + 1}. ${title}`));
// 模拟点击第一本书以演示用户操作
await page.click('ol.row li h3 a');
await new Promise(resolve => setTimeout(resolve, 1000)); // 等待加载图书页面
// DOM 操作:更改页面标题
await page.evaluate(() => {
document.querySelector('h1').innerText = 'Header changed with Puppeteer!';
});
// 创建 DOM 更改后的页面截图
await page.screenshot({ path: 'book_page.png', fullPage: true });
// 从当前页面生成 PDF 文档
await page.pdf({ path: 'book_page.pdf', format: 'A4' });
// 使用 MutationObserver 监控页面上的变化
await page.evaluate(() => {
const targetNode = document.body;
const observer = new MutationObserver((mutationsList) => {
for (let mutation of mutationsList) {
console.log('A change has been detected:', mutation);
}
});
observer.observe(targetNode, { childList: true, subtree: true, attributes: true });
});
await browser.close();
})()();
跟踪页面更改的单独代码(例如:"......")。g.,MutationObserver:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://books.toscrape.com/');
// 用于将数据从浏览器传递到 Node.js 的导出函数
await page.exposeFunction('onMutation', (mutations) => {
mutations.forEach(mutation => {
console.log('更改:', mutation); //记录更改
});
});
在页面上执行 MutationObserver
await page.evaluate(() => {
const targetNode = document.querySelector('.row'); // 观察装有书籍列表的容器
const config = { childList: true, subtree: true, attributes: true }; // 观察设置
const observer = new MutationObserver((mutationsList) => {
window.onMutation(mutationsList.map(突变 => ({
type: mutation.type、
addedNodes:Array.from(mutation.addedNodes).map(node => node.outerHTML)、
removedNodes:Array.from(mutation.removedNodes).map(node => node.outerHTML)
}));
}));
observer.observe(targetNode, config);
});
// 模拟交互以创建更改(如刷新页面)
await page.click('li.next a'); // 进入下一页以演示更改
// 等待 MutationObserver 捕捉变化
await new Promise(resolve => setTimeout(resolve, 5000));
await browser.close();
})()();
代码解析:
对更改的操作。 检测到更改时,数据将传递给 onMutation 函数,并在控制台中显示添加或删除的项目。
附加功能
检测隐藏的 API 站点
许多网站使用内部 API 来动态加载数据。这些请求通常不为普通用户所知,但 Puppeteer 可以帮助您发现它们。
- DevTools. 使用选项卡 Network 在浏览器开发工具中跟踪请求。Puppeteer 可以编程方式运行 DevTools 代理:
await page.setRequestInterception(true);
page.on('request', request => {
console.log(request.url());
request.continue();
});
- XHR 请求分析。 Puppeteer 捕获所有 XHR 请求,并可轻松查看返回的数据。
何时使用 Puppeteer 更好,何时使用 API 更好?
Puppeteer: 适用于需要模拟用户操作或处理 JavaScript 动态的复杂网站。
API: 最好用于结构化数据(如 JSON)和快速加载。如果网站提供官方 API,则这是一种更有效、更合法的信息收集方式。
自定义更改通知
- 使用 WebSockets 或 Webhooks: 将数据发送到服务器或信使(例如,使用 WebSockets 或 Webhooks)。g., Slack).
- 电子邮件集成: 检测到更改时发送电子邮件。
使用 Puppeteer 进行监控和通知的示例:
const puppeteer = require('puppeteer');
const nodemailer = require('nodemailer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com');
// 更改监控
const initialContent = await page.content();
;
setInterval(async () => {
const currentContent = await page.content();
if (currentContent !== initialContent) {
// 发送通知
sendEmail('Change on site!', 'Content has been updated.');
}
}, 30000); // 每 30 秒检查一次
;
async function sendEmail(subject, text) {
let transporter = nodemailer.createTransport({ /* SMTP settings */ });
await transporter.sendMail({ from: 'your_email', to: 'notify_email', subject, text });
}
await browser.close();
})();
与CapMonster Cloud集成用于CAPTCHA解决方案
网站通常使用验证码来防止自动数据收集。Puppeteer 允许您集成一个有效的工具来自动绕过不同类型的验证码 CapMonster CloudTo solve them: