本文共1451字,閱讀時間約4分鐘前端
Puppeteer是Chrome團隊出的nodejs庫(無頭瀏覽器),其中一個功能是網頁抓取(能夠做爲爬蟲使用)vue
詳細介紹請看gayhub,更新週期大約是一個月,本文是基於 v1.4.0寫的,大體api是通用的。 本文總結了Puppeteer爬蟲的主要用法。個人目標是,有了這篇文章,平常的通常爬蟲使用就不須要去看官方文檔了。node
cnpm i -S puppeteer
用cnpm安裝沒有試過報錯,默認會下載puppeteer配套版本的Chromium。git
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: false, //默認爲true(無頭),不顯示瀏覽器界面
slowMo :200, //減速顯示,有時會做爲模擬人操做特地減速
devtools: true //顯示開發者工具。頁面寬高默認800*600,把開發者工具顯示再隱藏頁面會佔滿屏幕,有沒有大佬解釋下?
});
//生成Page對象
//const page = await browser.newPage();//官網寫法:一打開瀏覽器會打開兩個tab,第二個纔是你正在操做的tab
const page = (await browser.pages())[0]; //這是個人寫法,只有一個tab
await page.goto('https://www.juejin.com'); //跳轉到掘金
//請開始你的表演...
await browser.close(); //關閉瀏覽器
})();
複製代碼
puppeteer基本上每一個操做都會返回一個Promise,記得要用await接收下一步的操做。github
puppeteer上也提供了一些第三方寫的爬蟲demo,不過感受封裝得有點多,先不玩。面試
頁面寬高默認800*600,我以爲過小。我通常都會先初始化頁面大小。正則表達式
和上面說的同樣,這只是初始化的時候的大小,當打開再隱藏開發者工具後,頁面就會佔滿全屏了,不知道這是否是bug。npm
await page.setViewport({
width: 1280,
height: 800
});
複製代碼
目測底層是用document.querySelector()api
await page.type(selector, 'Hello puppeteer'); //找到對應的選擇器而後填充值。若是以前設置了slowMo會看到像人打字同樣,值是一個一個填進<input/>
await page.click(selector); //模擬點擊,這對傳統異步分頁(url沒有分頁參數)頗有用,selector定在下一頁的標籤上
複製代碼
若是網頁內有用iframe等標籤,這時page對象是沒法讀取<iframe>
裏面的內容的,須要用到page.frames()
。返回一個Frame對象數組。 一般iframe會有name屬性,判斷name屬性能夠快速獲取單個Frame對象的內容。數組
let iframe = await page.frames();
iframe.find(f => f.name() === 'name')
複製代碼
waitFor函數是簡寫,Page和Frame對象都有。我只會用如下兩種方式,剩下了請大佬指點一下。
爲了簡化,Page和Frame對象都有的api,我不會再特地說明,會在代碼中直接體現。
await iframe.waitFor('.contain .item') //在<iframe>中等待'.contain .item'的節點出現,阻塞結束(ps:優先使用,有時200ms我是等不起的)
await page.waitFor(200)//頁面等待200ms
複製代碼
爲何要合在一點寫呢?由於確實有一個組合的api叫eval
先分開說說吧。
目測底層是用document.querySelector()和document.querySelectorAll()。熟悉這兩個api的人應該很容易上手。
//ps:較少用
page.$(selector) // document.querySelector()
iframe.$$(selector) // document.querySelectorAll(), $$是All的意思
複製代碼
這裏首先要有個概念,puppeteer爬蟲解析dom在瀏覽器,這個api的實參在瀏覽器中。因此能夠在這個函數內進行dom操做,同時本地的node api是沒法在這裏運行的,運行console.log(global)
會報錯。
舉個栗子:在函數內有console.log('按f12,我出如今瀏覽器的console中,並不在node命令行')
你會發現node命令行看不到這句話,而在Chromium的console中看見。所以你應該理解他的運行環境是當前網站,而不是你本地的node。
//ps:更少用
await page.evaluate(el => {
//喜聞樂見的dom操做
})
await iframe.evaluate(el => {
//請開始你的表演
console.log('按f12,我出如今瀏覽器的console中,並不在node命令行')
})
複製代碼
$eval
和 $$eval
上面的兩個api一塊兒用就變成了eval,我最經常使用的api之一。一個api頂上面兩個,集中一塊兒寫,舒服。
const result = await page.$eval(selector, el => {
//若是須要賦值要返回Promise
return new Promise(resolve => {
//...一波騷操做
//能夠用Dom api啦
reslove(obj)
})
});
await iframe.$$eval(selector, el => {...});
複製代碼
上文說過在page.evaluate
中用console
是不能在node命令行打印出來的,不過有了監聽事件就能夠改變這個規則了。也能夠在監聽事件裏面作容錯處理。
page.on('console', msg => {
console.log(msg);
});
複製代碼
我的以爲若是打印dom的話,仍是看瀏覽器的console比較好,直觀。
//監聽瀏覽器報錯
page.on('pageerror', pageErr => {
console.log(pageErr);
});
//監聽node報錯
page.on('error', err => {
console.log(err);
});
複製代碼
const devices = require("puppeteer/DeviceDescriptors");
const iPhone = devices["iPhone 6"];
...
await page.emulate(iPhone);
複製代碼
更多設備能夠查看這裏
以上就是我要介紹的puppeteer爬蟲api。
安利兩本書,一本是老姚的正則表達式pdf版說得很詳細,確實頗有用,雖然我已經忘了一大半了(╯﹏╰);另外一本是 Web 前端面試指南與高頻考題解析小冊子,內容基礎又豐富,但願我能夠找個機會實踐一下。
下面我要說說正事。
小弟不才,17年軟件工程畢業生,熟悉vue寫過兩個公司項目。目前已離職,座標廣州,求大佬們收留。