抓取網頁生成 PDF


看到自己喜歡的在線文檔,是不是總想保存下來慢慢學習。可是苦於沒有現成的工具,這里我來介紹兩個 JS 類庫,只需要簡單封裝一下,從此想抓哪里抓哪里。

一、使用 Phantomjs

1.簡單使用

 1 const phantom = require('phantom');
 2 (async function() {
 3   const instance = await phantom.create();
 4   const page = await instance.createPage();
 5   await page.on('onResourceRequested', function(requestData) {
 6     console.info('Requesting', requestData.url);
 7   });
 8   const status = await page.open('http://jartto.wang');
 9   await page.render('jarttoTest.pdf');
10   await instance.exit();
11 })();

 

上面是一個完整的示例,我們來看看最核心的部分,不妨放大一下:

 1 page.open(address, function (status) {
 2   if (status !== 'success') {
 3       // --- Error opening the webpage ---
 4       console.log('Unable to load the address!');
 5   } else {
 6       // --- Keep Looping Until Render Completes ---
 7       window.setTimeout(function () {
 8           page.render(output);
 9           phantom.exit();
10       }, 200);
11   }
12 });

嗯,結合起來,就完美了。下面就是最佳實踐:

 1 var page = require('webpage').create();
 2 page.open('http://jartto.wang', function(status) {
 3   setTimeout(function() {
 4       if ( status === 'success' ) {
 5         page.render('test.png');
 6         phantom.exit(); 
 7       } else {
 8         console.log('Page failed to load.'); 
 9       }
10   }, 200);
11 });

 

因為 open 操作會有響應時間,所以需要使用 setTimeout 來確保流程。

這里需要額外補充一點,如果需要檢測 UA,那么你需要這么使用:

1 var page = require('webpage').create();
2 page.userAgent = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36';
3 page.open('https://securelearning.in', function() {
4   page.render('image.png');
5   phantom.exit();
6 });

這里就不再細說了,更多細節可以查看 Demo

二、使用 Puppeteer

既然 Phantomjs 這么好用,為啥還要了解 Puppeteer ?

提到這個問題,我們不得不來說一下 Puppeteer 強大的官方背景:Puppeteer(木偶) 英[ˌpʌpɪˈtɪə(r)],美[ˌpʌpɪˈtɪr],是 Google Chrome 團隊官方的無界面 (Headless)Chrome 工具。所以不管從以后的發展還是完整性方面,Puppeteer 都是我們的首選。

那么,Puppeteer 能用來干啥,有哪些功能:

  • 生成頁面的截圖和 PDF
  • 爬取網站內容
  • 模擬登陸、自動提交表單,UI 測試,鍵盤輸入等
  • 使用最新的 JavaScript 和瀏覽器功能,直接在最新版本的 Chrome 中運行測試。
  • 捕獲網站的時間線跟蹤,以幫助診斷性能問題
  • 測試 Chrome 擴展程序

說了這么多,讓我們快速開始,迅速的體驗一把。

1.安裝

1 npm i puppeteer

2.注意事項

安裝並不會那么順利,因為要依賴 Chromium ,所以你可能會遇到這樣的異常。


Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, see Environment variables.

 

正確姿勢:

1 set PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
2 npm i puppeteer
3 # 或者忽略依賴腳本安裝 jartto's demo
4 npm i --save puppeteer --ignore-scripts

 

如果不能翻牆下載,那么就手動去官網下載 Chromium 吧。當然,坑遠不止這些,感興趣的童鞋可以戳這里 Puppeteer 異常處理

3.下載核心包

1 npm i puppeteer-core

從 1.7 版本開始發布 puppeteer-core ,他默認不會下載 Chromium 。puppeteer-core 使用已安裝的瀏覽器 或遠程瀏覽器。具體可以查看官網文檔 puppeteer vs puppeteer-core.

4.示例
生成網站快照:

1 const puppeteer = require('puppeteer');
2 (async () => {
3   const browser = await puppeteer.launch();
4   const page = await browser.newPage();
5   await page.goto('http://jartto.wang');
6   await page.screenshot({path: 'blog.png'});
7   await browser.close();
8 })();

通過網站地址,生成 pdf

1 const puppeteer = require('puppeteer');
2 (async () => {
3   const browser = await puppeteer.launch();
4   const page = await browser.newPage();
5   await page.goto('https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pdf', {waitUntil: 'networkidle2'});
6   await page.pdf({path: 'jartto.pdf', format: 'A4'});
7   await browser.close();
8 })();

設置視口:

1 await page.setViewport({width: 1024, height: 880});

設置 cookie

1 const COOKS =[
2   {
3   'domain': 'jartto.wang',
4   'name': 'user',
5   'value': 'jartto',
6   }
7 ]
8 await page.setCookie(...COOKS);

模擬設備 iphonex 來生成截圖:

 1 const devices = require('puppeteer/DeviceDescriptors');
 2 const puppeteer = require('puppeteer');
 3 (async () => {
 4   //創建瀏覽器示例對象
 5   const browser = await puppeteer.launch({
 6     executablePath: 'chromium/Chromium.app/Contents/MacOS/Chromium',
 7     headless: true
 8   });
 9   // 通過瀏覽器實例 Browser 對象創建頁面 Page 對象 
10   const page = await browser.newPage();
11   await page.emulate(devices['iPhone X']);
12   await page.goto('http://jartto.wang');
13   await page.screenshot({path: 'temp/iphonex.png'});
14  
15   await browser.close();
16 })().catch(error => console.log('error: ', error.message));

如果是本地的 chromium ,記得配置 executablePath: ‘chromium/Chromium.app/Contents/MacOS/Chromium’。

更有趣的事情是,我們可以搜索一些關鍵字來生成快照,譬如:

 1 const devices = require('puppeteer/DeviceDescriptors')
 2 const puppeteer = require('puppeteer');
 3 (async () => {
 4   const browser = await puppeteer.launch({
 5     executablePath: 'chromium/Chromium.app/Contents/MacOS/Chromium',
 6     headless: true
 7   });
 8   const page = await browser.newPage();
 9   await page.emulate(devices['iPhone X']);
10   await page.goto('https://www.baidu.com/');
11   // 輸入框 id,搜索關鍵字 jartto
12   await page.type('#index-kw', 'jartto');
13   // 模擬點擊提交按鈕
14   await page.click('#index-bn');
15   // 跳轉等待時間
16   await page.waitForNavigation({ timeout: 3000 });
17   await page.screenshot({path: 'temp/search.png'});
18   await browser.close();
19 })().catch(error => console.log('error: ', error.message));

執行上面的代碼,將會打開百度搜索引擎,同時搜索關鍵字 jartto,跳轉完成后進行截屏,保存成圖片。核心代碼:

1 // 輸入框 id,搜索關鍵字 jartto
2 await page.type('#index-kw', 'jartto');
3 // 模擬點擊提交按鈕
4 await page.click('#index-bn');
5 // 跳轉等待時間
6 await page.waitForNavigation({ timeout: 3000 });

一定要找准對應元素的 id,我們可以使用 chrome 開發者工具切換手機模式查看元素。

實際效果一覽,左圖為 blog 快照,右圖為搜索跳轉快照:

      
 

 

如果覺得例子還不夠,這里有個在線演示,以及我自己寫的 Demo

5.相關資源

學習資源總是很多,由淺入深的學習將會事半功倍,下面我稍微整理一下。

 

循序漸進的開始你的學習旅程吧。

三、總結

文章提供了兩種方式,在線抓取 URL 生成 PDF,當然插件的功能並不簡單如此,你還可以做更多有趣的事情。嗯,慢慢摸索、積累,相信我,總有一天你會用上的。

 

文章首發於 Jartto's blog


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM