首頁  >  文章  >  php框架  >  Laravel 中使用 puppeteer 擷取非同步載入的網頁內容

Laravel 中使用 puppeteer 擷取非同步載入的網頁內容

藏色散人
藏色散人轉載
2019-10-16 14:24:233282瀏覽

Laravel 中使用 puppeteer 擷取非同步載入的網頁內容

採集網頁內容是一項很常見的需求,比較傳統的靜態頁面,curl 就能搞定。但如果頁面中有動態載入的內容,例如有些頁面裡透過ajax 載入的文章正文內容,又如果有些頁面載入完成後進行了一些額外處理(圖片地址替換等等…)而你想擷取這些處理過後的內容。那麼牛逼閃閃的 curl 也束手無策了。

做過類似需求的人可能會說,老鐵,上 PhantomJS 啊!

沒錯,這是一個辦法,而且在相當長的時間裡 PhantomJS 是為數不多的能解決這類需求的工具裡的佼佼者。

但今天這裡要介紹的是一個後來居上的工具 -- puppeteer,它是隨著 Chrome Headless 技術興起而快速發展起來的。而且非常關鍵的是,puppeteer 由 Chrome 的官方團隊開發和維護,可以說相當可靠了!

puppeteer 是 js 套件,要在 Laravel 中使用,得借助另一神器spatie/browsershot。

安裝

安裝spatie/browsershot

browsershot 是composer 套件,出自於大神團隊spatie

$ composer require spatie/browsershot

安裝puppeteer

$ npm i puppeteer --save

也可以全域安全puppeteer 但就個人經驗而言,在專案中安裝是比較建議的做法,因為這樣不同專案不會同時受全域安裝的puppeteer 影響,此外專案中安裝也方便使用phpdeployer進行升級(phpdeploy 升級時不會影響線上專案運行,要知道升級/安裝puppeteer 可是很耗時的,有時候還不能保證一次成功)。

安裝puppeteer 時會下載Chromium-Browser,鑑於咱特殊國情,很有可能出現無法下載的情況,對此,就請大家各顯神通吧…

#使用

以擷取今日頭條手機版頁面文章內容為例。

use Spatie\Browsershot\Browsershot;
public function getBodyHtml()
{
    $newsUrl = 'https://m.toutiao.com/i6546884151050502660/';
    
    $html = Browsershot::url($newsUrl)
        ->windowSize(480, 800)
        ->userAgent('Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36')
        ->mobile()
        ->touch()
        ->bodyHtml();
    \Log::info($html);
}

運行後可以在日誌中看到如下內容(截圖中只是其中部分)

Laravel 中使用 puppeteer 擷取非同步載入的網頁內容

#此外,也可以將頁面儲存為圖片或PDF文件。

use Spatie\Browsershot\Browsershot;
public function getBodyHtml()
{
    $newsUrl = 'https://m.toutiao.com/i6546884151050502660/';
    
    Browsershot::url($newsUrl)
        ->windowSize(480, 800)
        ->userAgent('Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36')
        ->mobile()
        ->touch()
        ->setDelay(1000)
        ->save(public_path('images/toutiao.jpg'));
}

Laravel 中使用 puppeteer 擷取非同步載入的網頁內容

圖片裡那些框與系統字體有關。程式碼中使用了一個 setDelay() 方法,是為了讓內容載入完成後再進行截圖,簡單粗暴,可能不是最好的解決方法。

可能出現的問題

系統得支援Chromium 瀏覽器,當然現在絕大部分瀏覽器是支援的,要不然也沒法,還是用PhantomJS 吧。

專案中安裝了 puppeteer 後呼叫時有可能出現權限問題,這就需要對專案下 /node_modules/puppeteer 目錄賦予適當的權限。

總結

puppeteer 被應用在測試、採集等場景,是一個非常有力的工具。對於輕度的採集任務,是夠用的,例如本文這類在 Laravel (php) 裡來用採集一些小頁面,但如果需要快速採集大量內容,還是 Python 啥的吧

以上是Laravel 中使用 puppeteer 擷取非同步載入的網頁內容的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除