Puppeteer入門初探

網易雲社群發表於2018-09-27

本文來自網易雲社群

作者:唐釗


最近在看 node 爬蟲相關的一些東西,我記得還是很久以前常用的 node 爬蟲工具還是 superagengt+cherrio,他們的思路是通過發起 http 請求然後擷取 respone 的內容,但是隨著前端mvvm等框架的盛行,現在更多的內容是非同步載入了,所以通過這種傳統的爬蟲方式已經很難抓取到我們想要的內容了,那麼Puppeteer又有什麼亮點呢?接下來我們詳細介紹一下這個由 google 官方團隊維護的大殺器!

Puppeteer是一個Node庫,由Chrome官方團隊進行維護,提供介面來控制headless Chrome。Headless Chrome是一種不使用Chrome來執行Chrome瀏覽器的方式。簡單的來說就是一個執行在命令列中的 chrome,我們可以通過程式碼來實現我們常規的瀏覽器瀏覽網頁的功能。這樣就能保證我們拿到的內容和正常通過瀏覽器檢視的是一毛一樣的!


Puppeteer 核心功能

  • 利用網頁生成PDF、圖片

  • 爬取SPA應用,並生成預渲染內容(即“SSR” 服務端渲染)

  • 可以從網站抓取內容

  • 自動化表單提交、UI測試、鍵盤輸入等

  • 幫你建立一個最新的自動化測試環境(chrome),可以直接在此執行測試用例

  • 捕獲站點的時間線,以便追蹤你的網站,幫助分析網站效能問題

接下來我們通過一些簡單的示例來看一下它的使用


安裝

安裝還是常規的流程,通過yarn或npm來完成。只需執行下面的命令:

yarn add pupeeter//ornpm i -S puppeteer複製程式碼


DEMO

demo-截圖

const puppeteer = require("puppeteer");   //引入 puppeteer(async() => {    /*通過 launch 生成一個’瀏覽器‘例項,
    option 中的 headless 是個布林值,如果是 false 的話你就會看到一個瀏覽器從開啟,到完成你整個任務的全過程,
    預設是 true,也就是在後臺自動完成你的任務
    */
    const browser = await puppeteer.launch({ headless: false });  
    //開啟一個新的標籤頁
    const page = await browser.newPage();    //跳轉到我們想要的地址去
    await page.goto("http://www.hockor.com/");    //預設開啟的視口大小是800X600 ,我們可以通過如下程式碼來設定視窗的大小,
    await page.setViewport({
        width:1920,
        height:1080
    })    //通過screenshot方法完成截圖,並且儲存在指定的 path 中
    await page.screenshot({ path: "nba.png" });    //最後關閉整個‘瀏覽器‘
    browser.close();
})();複製程式碼

過程如下:

Puppeteer入門初探


demo-通過搜尋引擎拉取圖片

上面我們展示了 puppeteer一個基礎的 demo 完整例項,但是它更強大的地方還有很多,不僅支援在網頁上點選,還可以填寫表單,讀取資料。大家可以去官方 api 檢視,傳送連結

接下來開始我們下一個 demo,這個示例我們完成一個在搜尋引擎中爬取我們想要的圖片並儲存到本地的功能。來更進一步的瞭解這個強大的工具。

  • 我們的任務是在搜狗圖片中爬取關鍵詞為“NBA”的圖片,並且儲存在我們當前的 imgs 目錄下。

那麼核心的關鍵點就在於輸入我們的關鍵詞並且跳轉到對應的列表頁面,然後爬取內容中所有的 img 標籤,並將其儲存在我們制定的目錄中。接下來我們詳細剖析。

通過檢視Puppeteer API,可以找到定義點選的函式和聚焦的函式:

page.click(selector[, options])
page.focus(selector);複製程式碼

以上selector 一個選擇器來指定要點選的元素。如果多個元素滿足,那麼預設選擇第一個。 這不正好滿足了我們前面的邏輯,輸入框聚焦和點選,那麼怎麼輸入關鍵詞呢?

For finer control, you can use keyboard.down, 
keyboard.up, and keyboard.sendCharacter to manually 
fire events as if they were generated from a real keyboard.複製程式碼

可以看到我們可以通過 page.keyboard.sendCharacter 來輸入我們自己的文字

正好,這樣子我們就滿足了我們前期的條件,那麼完整的程式碼如下

const puppeteer = require("puppeteer");
(async ()=>{    const brower = await puppeteer.launch();    const page = await brower.newPage();
    await page.goto("http://pic.sogou.com/");
    await page.setViewport({
        width:1920,
        height:1080
    })    //上面的程式碼和之前是一樣的,不同是下面幾句
    //
    await page.focus("#form_querytext");
    await page.keyboard.sendCharacter("nba");
    await page.click("#searchBtn")

    await page.waitFor(1000);    //監聽頁面 load 完成
    page.on('load',async ()=>{        console.log("page loaded");        const srcs = await page.evaluate(()=> {            const images = document.querySelectorAll("img.img-hover");            return Array.prototype.map.call(images,img=>img.src)
        })        //遍歷圖片並且儲存
        srcs.forEach(async (src)=> {            console.log(src)            const ext = path.extname(src) ? path.extname(src):".jpg";            const file = path.join('./imgs',`${Date.now()}${ext}`)
            http.get(src,res=>{
                res.pipe(fs.createWriteStream(file)).on('finish',(err)=>{                    if(err){                        console.log(err)
                    } else {                        console.log("done")
                    }
                })
            })
        })
        await brower.close()
    })
})()複製程式碼

我們可以看到上面的流程就像我們正常瀏覽網頁一樣,而不是以前那種在 http response 中去抓取內容,這樣子對於現在的很多懶載入頁面或者前端渲染來講我們都能成功的爬取到我們想要的內容。

更多的官方 demo 例子我們可以去try-puppeteer.appspot.com/編輯檢視。

目前 puppeteer在爬蟲和前端自動化測試上使用也日益增大,大家可以去官方 API 文件檢視它的更多功能!大家也可以結合自己的需求/業務場景,充分挖掘Puppeteer功能。


網易雲免費體驗館,0成本體驗20+款雲產品!

更多網易研發、產品、運營經驗分享請訪問網易雲社群


相關文章:
【推薦】 網易雲易盾CTO朱浩齊:我們是如何用AI賦能內容安全?
【推薦】 Android優化之記憶體優化倒數計時篇
【推薦】 JVM鎖實現探究2:synchronized深探


相關文章