之前寫的兩篇爬蟲體驗基本上涵蓋了一般的Html頁面提取場景,但是有些時候,如果目標頁面不是純靜態的頁面,而是使用js動態渲染的頁面(比如one),之前的爬蟲就不好使了,這種時候就要借助一些其他工具來進行實現。
一般爬取動態頁面的思路是通過軟件模擬瀏覽器行為獲取到渲染后的頁面鏡像,然后再對渲染后的頁面進行分析,常用的工具有selenium,phantomJs,puppeteer等,通過對項目維護程度、對PHP友好度的對比,我選用的是puppeteer。
根據官方介紹,谷歌在2017年開發了自家Chrome瀏覽器的Headless特性,puppeteer便是這個時候誕生的,它的原理是通過調用Chrome DevTools開放的接口與Chrome通信,將瀏覽器開放接口進行封裝,方便用戶調用,可以很容易地實現瀏覽器行為的模擬。
嘗試一下puppeteer,安裝起來其實非常簡單:
npm i puppeteer
根據官方API寫了example.js進行測試:
async function start(){ const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('http://wufazhuce.com'); return page.content(); }; (async () => { const a = await start(); process.stdout.write(a); })();
執行node example.js便可以看到控制台輸出了渲染完成之后的頁面Html,這個時候便能夠使用php的fopen讀取stdout獲取到html文本進行下一步處理了。
在github上面查找相關支持,發現有spatie/browsershot這個項目直接把操作步驟封裝好了,這樣便可以使用puppeteer進行動態生成html內容的獲取,然后繼續使用dom-crawler來獲取想要抓取的內容了:
$this->crawler = new Crawler(); $html = Browsershot::url($this->url) ->setOption('args', [ '--no-sandbox', '--disable-setuid-sandbox' ]) ->bodyHtml(); $this->crawler->addHtmlContent($html);