Web Scraping 和 Puppeteer:如何轻松跟踪网页更改?数据自动化指南》
What is web scraping and why is needed?
网页刮擦是一种从网页中自动收集数据的简单方便的方法。无需手动复制信息,由专门的程序代劳,从网站内容中提取所需的数据。Web scraping 节省了时间,简化了日常任务,并使您能够实时掌握变化。9999999999999999998pt;">Web scraping 如何工作? 当信息量大、不断变化或呈现方式不方便时,这一点尤其有用。Why is important to track changes on websites?"
互联网每时每刻都在发生变化,手动跟踪所有内容非常困难,而且在有机会使用自动化的情况下也没有必要。下面举例说明为什么需要自动化:
- Price Changes
想象一下,您正在网上商店寻找最优惠的商品。产品的价格会随着时间、季节或竞争对手的活动而变化。网络搜刮将帮助您快速找到最低价格,或及时调整商品成本。
- Availability of goods
如果您想购买经常供不应求的热门商品,该脚本将帮助您跟踪该商品何时再次上市。它有助于企业了解供应商的库存情况。
- 新闻和更新
跟踪重要页面的最新消息、出版物或更改将帮助您了解最新情况。例如,您可以设置从新闻网站或博客收集信息。
- 竞争对手监控
企业需要了解竞争对手在做什么:他们正在进行哪些促销活动,他们在商品种类中添加了哪些新内容,他们获得了哪些评论。网络搜索可以轻松完成这一任务。
现代网站通常不会立即上传数据,而是在用户采取行动时上传,例如评论、评级或统计数据。手动收集此类数据非常耗时,而自动化将在数秒内完成所有工作。
Puppeteer:什么是 Puppeteer,为什么在网络搜刮中需要它?
从网站收集信息需要方便可靠的工具。其中,Puppeteer 是一个用于 Node.js 的库。js 的库,它允许您模拟真实用户的操作:打开页面、点击元素、填写表格甚至截图 - 所有操作均为全自动模式。38;margin-bottom:0pt;margin-top:0pt;" dir="ltr">使用 Puppeteer 进行网页刮擦变得更加容易,尤其是涉及使用 JavaScript 加载内容的动态网站时。Puppeteer 不仅能 "看到 "用户所看到的内容,还能让您与这些内容进行更深层次的交互,因此非常适合数据收集、网站测试和任何复杂任务的自动化。如果您使用的是 JavaScript 和 TypeScript,那么 Puppeteer 将是您进行 Web 搜索和许多其他任务的最佳选择!
Benefits of Puppeteer
使其如此受欢迎的主要优点:
- Working with dynamic content
常见的搜索工具(如 Axios、Cheer 等)。例如 Axios、Cheerio)在处理使用 JavaScript 动态加载内容的网站时经常会遇到困难。而 Puppeteer 在这方面做得很好!它运行一个成熟的浏览器(谷歌 Chrome 浏览器或火狐浏览器),允许你像真正的用户一样加载页面。这意味着所有内容,甚至是脚本执行后出现的内容,都可用于分析和数据收集。
- Element Manipulation
Easily interact with the DOM - add or remove elements, click buttons, fill out forms, scroll pages, and more.
- Headless-mode
Puppeteer 允许您在正常模式和无头模式(无图形用户界面)下控制浏览器。
无头模式 - 实现快速、谨慎自动化的理想选择:浏览器在 "后台 "运行,节省资源并加快任务执行速度。
完整浏览器模式 - 对于调试和开发非常有用:您可以直观地观察页面上发生的情况。
- Device Emulation
Puppeteer 还可以通过更改用户代理标头来模拟设备,这有助于绕过封锁和限制网站。您甚至可以模拟 3G 或 Wi-Fi 等网络模式来测试页面性能。
- 屏幕截图和 PDF 创建
您可以拍摄页面快照或将其保存为 PDF 文件。这对于创建报告、记录网页内容或测试非常有用。
我们将在下文中详细讨论所有这些优势。
所以说,Puppeteer 不仅仅是一个刮擦工具,而且是任何浏览器自动化相关任务的通用助手。999999999999999999999999998pt;">Puppeteer
- 该库的安装非常简单。首先,确保您已安装 Node.js ( 官方网站).
- 然后打开终端或命令提示符并运行 npm 命令:
npm i puppeteer
此命令会自动下载最新版本的 Chromium。如果 Chromium 已安装或您想使用其他浏览器,则可以不安装 Chromium 而直接安装 Puppeteer:
npm i puppeteer-core
Working with DOM and user actions
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; });
Parameters for Web Scraping with 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']。
});
- Cookie 和会话管理:
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();
})()();
代码解析:
Expose Function. Method page.exposeFunction() 允许您创建一个函数 onMutation() ,该函数将从浏览器向 Node.js 环境传递更改数据。
MutationObserver.B page.evaluate() 我们在页面上实现了 MutationObserver。它跟踪指定元素(.行) 书籍所在的位置.
config 定义要跟踪的更改:
childList: 添加或删除子代。
subtree: 监督所有儿童。
属性: 元素属性更改。
对更改的操作。 检测到更改时,数据将传递给 onMutation 函数,并在控制台中显示添加或删除的项目。38;margin-bottom:0pt;margin-top:0pt;" dir="ltr">Additional Features
检测隐藏的 API 站点
许多网站使用内部 API 来动态加载数据。这些请求通常不为普通用户所知,但 Puppeteer 可以帮助您发现它们。
- DevTools. 使用选项卡 Network 在浏览器开发工具中跟踪请求。Puppeteer 可以编程方式运行 DevTools 代理:
await page.setRequestInterception(true);
page.on('request', request => {
console.log(request.url());
request.continue();
});
XHR 请求分析。 Puppeteer 捕获所有 XHR 请求,并可轻松查看返回的数据。38;margin-bottom:0pt;margin-top:0pt;" dir="ltr">何时使用 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();
})();
CAPTCHA 解决方案与 CapMonster 云的集成
网站通常使用验证码来防止自动数据收集。Puppeteer 允许您集成一个有效的工具来自动绕过不同类型的验证码 CapMonster CloudTo solve them:
- 安装官方库:
npm i @zennolab_com/capmonstercloud-client
- 从亚马逊提取动态验证码数据并使用 CapMonster Cloud:
const puppeteer = require('puppeteer');
const { CapMonsterCloudClientFactory, ClientOptions, AmazonProxylessRequest }= require('@zennolab_com/capmonstercloudclient');
(async () => {
const browser = await puppeteer.launch({ headless: false }); // 设置为 true 时为无头模式
const page = await browser.newPage();
const pageUrl = 'https://example.com'; // 验证码页面的 URL
await page.goto(pageUrl);
// 从网页中读取验证码参数
const captchaParams = await page.evaluate(() => {
const gokuProps = window.gokuProps || {};
const scripts = Array.from(document.querySelectorAll('script'));
返回 {
websiteKey: gokuProps.key |||"Not found"、
context:gokuProps.context || "Not found"、
iv: gokuProps.iv|| "Not found"(未找到)、
challengeScriptUrl:scripts.find(script => script.src.includes('challenge.js'))?.src || "未找到"、
captchaScriptUrl: scripts.find(script => script.src.includes('captcha.js')?.src || "Not found"?
};
});
console.log('Captcha Parameters:', captchaParams); // 检查提取的参数
// 创建一个发送到 CapMonster 云服务器的任务
const cmcClient = CapMonsterCloudClientFactory.Create(new ClientOptions({)
clientKey:'your_api_key', // 替换为您的 CapMonster 云 API 密钥
})));
// 自定义验证码查询
const amazonProxylessRequest = new AmazonProxylessRequest({
websiteURL: pageUrl、
challengeScript: captchaParams.challengeScriptUrl、
captchaScript:captchaParams.captchaScriptUrl、
websiteKey: captchaParams.websiteKey、
context:captchaParams.context、
iv:captchaParams.iv、
cookieSolution:false、
});
// 验证码解决方案
const response = await cmcClient.Solve(amazonProxylessRequest);
if (!response?.solution) {
console.error('CAPTCHA not solved.');
await browser.close();
process.exit(1);
}
console.log('Captcha Solved:', response.solution);
await browser.close();
console.log('DONE');
process.exit(0);
})()
.catch(err => {
console.error(err);
process.exit(1);
});
Ethics and legal aspects of web scraping
请务必牢记 道德规范并遵守既定规则以确保网络搜刮合法、安全。负责任的网络搜刮的主要原则:
- Robots.txt: 检查 robots.txt 文件的指令,该文件决定了哪些网页可以被刮擦,哪些不能:
允许:/public/
禁止:/admin/
禁止:/private/
https://example.com/robots.txt)或使用 Puppeteer:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
// robots.txt 文件的 URL
const robotsUrl = 'https://example.com/robots.txt';
await page.goto(robotsUrl);
// 获取 robots.txt 文本
const robotsText = await page.evaluate(() => document.body.innerText);
console.log('Contents of robots.txt:\n', robotsText;)
await browser.close();
})();
- 有必要限制请求的频率 以免服务器超载。在请求之间使用延迟(await page.waitForTimeout(3000);)。
- Legal aspects:
遵守国家法律,确保刮擦不违反当地法律。
未经许可,请勿发布受版权保护的数据。
Some sites require explicit permission to collect data.
现在,我们已经分解了 Puppeteer 用于网页刮擦的主要功能,现在可以得出结论:它是自动从网页收集数据的有效方法,可以节省时间并实时提供相关信息。该工具可以轻松处理动态内容、模拟用户操作和各种 DOM 操作。38;margin-bottom:0pt;margin-top:0pt;" dir="ltr">本文包含演示数据提取和处理动态内容的代码示例。这些示例将帮助您更快地学习网络刮擦并使其适应您的需求。
Puppeteer 适用于需要高精度的任务,如价格监控或新闻追踪。无头模式和灵活配置的使用有助于优化您的工作。
Puppeteer 不仅是一款刮擦工具,还是测试和各种自动化任务的多功能解决方案。我们希望这篇评论能帮助您入门,并激励您创建自己的自动化解决方案!"
NB:请注意,该产品用于在您自己的网站和您拥有合法访问权限的网站上自动进行测试.
。