puppeteer 是一个Chrome官方出品的headless Chrome node库。它提供了一系列的API, 能够在无UI的状况下调用Chrome的功能, 适用于爬虫、自动化处理等各类场景
html
根据官网上描述,puppeteer 具备如下做用:vue
如下就来阐述 puppeteer 的这几个做用node
注: 这里咱们会使用到 es6/7 的新特性,因此用 typescript 来编译代码python
npm install puppeteer typescript @types/puppeteer
复制代码
tsconfig.json 配置以下:react
{
"compileOnSave": true,
"compilerOptions": {
"target": "es5",
"lib": [
"es6", "dom"
],
"types": [
"node"
],
"outDir": "./dist/",
"sourceMap": true,
"module": "commonjs",
"watch": true,
"moduleResolution": "node",
"isolatedModules": false,
"experimentalDecorators": true,
"declaration": true,
"suppressImplicitAnyIndexErrors": true
},
"include": [
"./examples/**/*",
]
}
复制代码
puppeteer 模块提供一个方法启动一个 Chromium 实例。ios
import * as puppeteer from 'puppeteer'
(async () => {
await puppeteer.launch()
})()
复制代码
上述代码经过 puppeteer 的 launch 方法生成一个 browser 实例,launch 方法能够接收一些配置项。较为经常使用的有:git
这里咱们以 example.com/为例es6
(async () => {
const browser = await puppeteer.launch(); //生成browser实例
const page = await browser.newPage(); //解析一个新的页面。页面是在默认浏览器上下文建立的
await page.goto("https://example.com/"); //跳转到 https://example.com/
await page.screenshot({ //生成图片
path: 'example.png'
})
})()
复制代码
在这里须要注意的是,截图默认截取的是打开网页可视区的内容,若是要获取完整的可滚动页面的屏幕截图,须要添加 fullPage: true
github
执行node dist/screenshot.js
,便可在根目录下生成 example.pngchrome
puppeteer 默认将页面大小设置为 800*600,能够经过page.setViewport()
来改变页面大小。
不只如此,puppeteer 还能够模拟手机
import * as puppeteer from "puppeteer";
import * as devices from "puppeteer/DeviceDescriptors";
const iPhone = devices["iPhone 6"];
(async () => {
const browser = await puppeteer.launch({
headless: false
});
const page = await browser.newPage();
await page.emulate(iPhone);
await page.goto("https://baidu.com/");
await browser.close();
})();
复制代码
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("https://example.com/");
await page.pdf({
displayHeaderFooter: true,
path: 'example.pdf',
format: 'A4',
headerTemplate: '<b style="font-size: 30px">Hello world<b/>',
footerTemplate: '<b style="font-size: 30px">Some text</b>',
margin: {
top: "100px",
bottom: "200px",
right: "30px",
left: "30px",
}
});
await browser.close();
})()
复制代码
执行 node dist/pdf.js
便可。
在这里咱们模拟一下github的登陆, 为了能更好的看到整个过程, 咱们使用 headless: false
来关闭 headless 模式,看一下整个的登陆流程
(async () => {
const browser = await puppeteer.launch({
headless: false
});
const page = await browser.newPage();
await page.goto("https://github.com/login");
await page.waitFor(1000) //延迟1秒输入
await page.type("#login_field", "帐号"); //当即输入
await page.type("#password", "密码", {
delay: 100
}) //模拟用户输入
await page.click("input[type=submit]"); //点击登陆按钮
})()
复制代码
执行node dist/login.js
能够很方便的使用 tracking.start
和 tracking.stop
建立一个能够在 chrome devtools 打开的跟踪文件
(async () => {
const broswer = await puppeteer.launch();
const page = await broswer.newPage();
await page.tracing.start({
path: "trace.json"
});
await page.goto("https://example.com/");
await page.tracing.stop();
broswer.close();
})();
复制代码
执行 node dist/trace.js
会生成一个 trace.json 文件, 而后咱们打开 chrome devtools -> Performance, 而后把该文件直接拖进去便可。该功能便于咱们对网站进行性能分析, 进而优化性能
如今大多数开发用 react、vue、angular 来构建 SPA 网站, SPA 固有不少的优势, 比方开发速度快、模块化、组件化、性能优等。但其缺点仍是很明显的, 首先就是首屏渲染问题, 其次不利于 SEO, 对爬虫不友好。
以 preview.pro.ant.design/#/dashboard… 为例, 咱们点击右键, 查看源代码, 发现其 body 里面只有 <div id="root"></div>
,假如想把门店销售额排名状况给爬下来,存到数据库进行数据分析(以下图)
如 python
# -*- coding : UTF-8 -*-
from bs4 import BeautifulSoup
import urllib2
def spider():
html = urllib2.urlopen('https://preview.pro.ant.design/#')
html = html.read()
soup = BeautifulSoup(html, 'lxml')
print(soup.prettify())
if __name__ == '__main__':
spider()
复制代码
执行 python py/index.py
, 获得的结果以下图:
nodejs
import axios from "axios";
(async () => {
const res = await axios.get("https://preview.pro.ant.design/#");
console.log(res.data);
})();
复制代码
执行node dist/node-spider.js
, 获得和上面例子同样的结果。
puppeteer
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("https://preview.pro.ant.design/#");
console.log(await page.content());
})();
复制代码
执行node dist/spider.js
, 获得以下:
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("https://preview.pro.ant.design/#");
const RANK = ".rankingList___11Ilg li";
await page.waitForSelector(RANK);
const res = await page.evaluate(() => {
const getText = (v, selector) => {
return v.querySelector(selector) && v.querySelector(selector).innerText;
};
const salesRank = Array.from(
document.querySelectorAll(".rankingList___11Ilg li")
);
const data = [];
salesRank.map(v => {
const obj = {
rank: getText(v, "span:nth-child(1)"),
address: getText(v, "span:nth-child(2)"),
sales: getText(v, "span:nth-child(3)")
};
data.push(obj);
});
return {
data
};
});
console.log(res);
await browser.close();
})();
复制代码
执行node dist/spider.js
, 获得以下:
此时,咱们已经利用 puppeteer 把咱们所须要的数据给爬下来了。
到此,咱们就把 puppeteer 基本的功能点给实现了一遍,本文示例代码可在github上获取。