看到自己喜歡的在線文檔,是不是總想保存下來慢慢學習。可是苦於沒有現成的工具,這里我來介紹兩個 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