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上獲取。