从零开始学习 puppeteer(一)
·
Yin灏
Puppeteer 通常用在自动化测试和爬取页面,提供丰富 api 来控制 headless Chrome 或者 Chromium。
安装
npm 包比较大,推荐全局安装。
npm i puppeteer
# or using yarn
yarn add puppeteer
# or using pnpm
pnpm i puppeteer
使用
环境配置
pnpm init -y
pnpm i puppeteer
touch demo.js
刚开始先通过 node demo.js
运行项目。
官方案例
-
puppeteer.launch
创建 Browser 实例,类似打开浏览器 -
browser.newPage
创建 Page 实例,类似浏览器中新开页面 -
browser.close()
关闭浏览器。
const puppeteer = require("puppeteer");
(async () => {
// 1. 创建了Browser实例,类似打开浏览器
const browser = await puppeteer.launch({
headless: "new",
});
console.log("打开浏览器");
// 2. 创建了Page实例,类似浏览器中新开页面
const page = await browser.newPage();
console.log("打开页面");
// 导航到要访问的页面
await page.goto("https://www.baidu.com");
await page.screenshot({ path: "example.png" });
console.log("success");
// 在页面中执行脚本 Get the "viewport" of the page, as reported by the page.
const dimensions = await page.evaluate(() => {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
deviceScaleFactor: window.devicePixelRatio,
};
});
console.log("Dimensions:", dimensions);
// 设置可视区域
await page.setViewport({
width: 1420,
height: 1000,
});
// 全屏截取
await page.screenshot({
path: "example1.png",
fullPage: true,
});
// waitUntil 来配置什么时候导航结束 "domcontentloaded"、"networkidle0"、"networkidle2"
await page.goto("https://news.ycombinator.com", {
waitUntil: "networkidle2",
});
await page.pdf({ path: "hn.pdf", format: "A4" });
console.log("success pdf");
// 3. 关闭浏览器
await browser.close();
})();
page.goto
用于导航到新页面,waitUntil
是指定一个等待条件,告诉 puppeteer 合适导航完成。默认取值 load, 还有 documentloaded
等待页面 DOMcontentLoaded
事件触发。
page.evaluate
功能类似 eval
,在浏览器中执行脚本,结果返回程序。
page.$(selector)
就是 document.querySelector,而 page.$$(selector)
则是 document.querySelectorAll.
这个 case 仅仅是整合了官方最简单的三个案例。运行一遍,有个概念。
拓展 - 滚动截屏
很多网站数据是懒加载的,如果想要把所有的数据获取到,则需要一些相关的元素操作,比如滚动。
const puppeteer = require("puppeteer");
(async () => {
const browser = await puppeteer.launch({
headless: "new",
});
console.log("打开浏览器");
const page = await browser.newPage();
console.log("打开页面");
// demo 懒加载及数据滚动加载
await scrollLoad(page);
await browser.close();
})();
// 懒加载及数据滚动加载
async function scrollLoad(page) {
await page.goto("https://www.jd.com/", {
waitUntil: "networkidle2",
});
// setViewport setUserAgent
// await page.emulate(puppeteer.KnownDevices['iPhone 13 Pro Max']);
await page.emulate({
viewport: {
width: 375,
height: 667,
isMobile: true,
},
userAgent:
'"Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1"',
});
// 获取element内容
const result = await page.$eval("#hotwords", (el) => {
return el.innerText;
});
console.log("page.$eval", result);
// element 输入
const inputEle = await page.$("#search input");
await inputEle.type("macbook pro", {
delay: 300,
});
// element点击
// const btnEle = await page.$("#search button");
// await btnEle.click();
await autoScroll(page);
//全屏截取
await page.screenshot({
path: "jd-all.png",
fullPage: true,
});
}
// 工具函数 - 自动滚动
async function autoScroll(page) {
await page.evaluate(async () => {
await new Promise((resolve) => {
let totalHeight = 0;
const distance = 200;
const timer = setInterval(() => {
const scrollHeight = document.body.scrollHeight;
window.scrollBy(0, distance);
totalHeight += distance;
if (totalHeight >= scrollHeight) {
clearInterval(timer);
resolve();
}
}, 200);
});
});
}
参考资料
- Puppeteer 入门简介
- 官方文档 EN: pptr.dev/ CN: puppeteer.bootcss.com/