使用 CasperJS 構建 Web 爬蟲
從你的應用中收集資料有時候可能有點困難和艱辛。可能是缺少一個必須的API,或者是有太多的資料需要處理。這時候你就需要藉助於web抓取。
不用說了,這可能是個法律雷區,所以要確保你沒有逾越法律的邊界。
目前有很多工具可以幫助你抓取內容,例如Import.io,但是有時這些工具並不能完全滿足你的需要。又或者,像我一樣,充滿好奇心,希望深入地瞭解web抓取。
挑戰
讓我們從一個簡單地挑戰——網路爬蟲開始,讓這個爬蟲爬取Techmeme,並獲得一個當天熱門新聞列表!
注意: 在這裡我將會使用DZone,但在獲取頁面時會出現問題。後面會詳細說明這個問題。
機器設定
您只需要做很少的工作來完成安裝。我假設您已經安裝了Node.js(我的意思是誰沒有安裝呢!)。儘管我們並不直接使用PhantomJS,但是您依然需要安裝它。版本2.0.1目前已經可以使用了——您可以從其官網下載或使用homebrew或其他等效的包管理器安裝。
如果您使用具有homebrew的Mac,您可以這樣安裝PhantomJS
brew install phantomjs
下載完成之後,您將需要用相同的方式安裝CasperJS。您可以將CasperJS看做PhantomJS的伴侶。它實際上是給您提供相似的網頁處理API。儘管它是為網頁測試設計的。與PhantomJS相同,它具有豐富的功能使其也非常適合於抓取內容。
CasperJS允許我們編寫JavaScript指令碼。您可以通過在終端中輸入casperjs以測試其是否正確安裝並加入到PATH中。
編寫指令碼
下面我們將編寫一個新的JavaScript指令碼檔案。在我的例子中,我稱其為index.js。您需要做的第一件事就是在您的程式碼中建立一個casper例項。您還需要加入依賴的模組並向其傳遞一些基本引數。
var casper = require("casper").create({ waitTimeout: 10000, stepTimeout: 10000, verbose: true, pageSettings: { webSecurityEnabled: false }, onWaitTimeout: function() { this.echo('** Wait-TimeOut **'); }, onStepTimeout: function() { this.echo('** Step-TimeOut **'); } });
當您等待一個元素可見時,上面的onWaitTimeout回撥將會被呼叫。例如,點選一個按鈕之後,waitTimeout將被超出。
現在,您可以啟動casper例項並將其指向我們希望爬取的頁面。
casper.start(); casper.open("http://techmeme.com");
Casper使用一個可靠地框架來幫助您一步一步地執行所有任務。對於第一步,您將希望使用then函式。
casper.then(function() { //logic here }); //start your script casper.run();
為了使Casper開啟網頁並按您的想法執行,您需要呼叫run函式。
檢查網頁以獲取想要的元素
當抓取到一個網頁,您可以假設它具有特定的結構。在您編寫指令碼之前,可能已經瀏覽過了網頁的原始碼,或者已經使用開發者工具觀察了頁面對特定行為的變化。
所以,讓我們開始於一個簡單地邏輯,使用CasperJS維護系統確保一個特定的元素在繼續之前處於合適的位置。如果元素不存在,指令碼將會停止,但是至少您將會知道其為何停止。這個維護行為對於觀察您之前抓取頁面的變化是無價的,但是可能會與您之前見到的頁面具有不一樣的結構。
如果您檢查了Techmeme首頁的元素,您將會注意到頭條新聞部分在一個id為,topcol1的div中。
讓我們使用維護功能確保這個元素存在:
casper.then(function() { this.test.assertExists("#topcol1");
如果這個元素不存在,測試(例如我們的指令碼)將會停止,否則它將繼續執行。
您還可以使用waitForSelector函式來獲得更為細緻的結果:
this.waitForSelector("#topcol1", function pass () { console.log("Continue"); }, function fail () { this.die("Did not load element... something is wrong"); } );
使用這個函式的優點就是它允許頁面載入元素並一直等待到執行。您在初始配置中指定的waitTimeout將會被用於確定失敗前等待多久。
注意:有時,使用CasperJS查詢元素可能會出問題。使用capture()函式擷取一個CasperJS看到的頁面的截圖。
this.capture(‘screener.png’);
從頁面中提取內容
下面,讓我們看看怎樣從頁面中找出標題。首先,找到包含您需要的內容的元素,在我們的例子中,為class=ii的div。
CasperJS自帶一個evaluate函式,可以讓您在頁面中執行JavaScript,並且您還可以讓函式返回一個值以供進一步處理。
這個JavaScript寫起來並沒有什麼不同,您可能注意到,在本例中,我使用的是原始的純DOM方法,而不是jQuery,同樣,如果您願意,您也可以在evaluate函式中使用jQuery;
var links = this.evaluate(function(){ var results = []; var elts = document.getElementsByClassName("ii"); for(var i = 0; i < elts.length; i++){ var link = elts[i].getElementsByTagName("a")[0].getAttribute("href"); var headline = elts[i].firstChild.textContent; results.push({link: link, headline: headline}); } return results; });
如果您在evaluate函式中使用console.log語句,它們將會通過remote.message控制程式碼列印到您的控制檯,這將會在下一節中詳細介紹。
一旦執行結束,結果將會返回給您。您可以將它們寫入檔案系統,或者將它們列印到螢幕上:
console.log("There were " + links.length + " stories"); for(var i = 0; i < links.length; i++){ console.log(links[i].headline); }
輸出的結果如:
抓取中的錯誤處理
有時,您執行的JavaScript中可能存在錯誤,或者其對您抓取的頁面的處理存在問題。這些情況中,您可以捕獲錯誤並使用remote.message和page.error事件將其列印到控制檯:
casper.on('remote.message', function(msg) { this.echo('remote message caught: ' + msg); }); casper.on('page.error', function(msg, trace) { this.echo('Error: ' + msg, 'ERROR'); });
您同樣還能觀察到即將請求的資源,這些資源的載入使用的是resource.error和resource.received事件:
casper.on('resource.error', function(msg) { this.echo('resource error: ' + msg); }); casper.on('resource.received', function(resource) { console.log(resource.url); });
瞭解更多
本文只寫了點關於使用CasperJS你所能做到的皮毛的東西。該專案的文件是完美的,所以要確保檢視過 API ,看看你還可以用它來做些什麼。
在本系列的下一篇文章中,我回來看看如何從網頁上下載圖片,而且我也會討論下如何使用構建到CasperJS中的檔案系統函式,其使用會受到比Node.js更多的限制。
相關文章
- 3 行寫爬蟲 - 使用 Goribot 快速構建 Golang 爬蟲爬蟲Golang
- 三篇文件學會使用casperjs製作爬蟲JS爬蟲
- 使用Scrapy構建一個網路爬蟲爬蟲
- (1)使用superagent和cheerio構建簡單爬蟲爬蟲
- python網路爬蟲(9)構建基礎爬蟲思路Python爬蟲
- 構建一個給爬蟲使用的代理IP池爬蟲
- 使用python/casperjs編寫終極爬蟲-客戶端App的抓取PythonJS爬蟲客戶端APP
- Scrapy 示例 —— Web 爬蟲框架Web爬蟲框架
- 快速構建Python爬蟲IP代理池服務Python爬蟲
- 爬蟲入門系列(三):用 requests 構建知乎 API爬蟲API
- 如何構建一個分散式爬蟲:基礎篇分散式爬蟲
- 如何構建一個分散式爬蟲:理論篇分散式爬蟲
- 如何構建一個分散式爬蟲:實戰篇分散式爬蟲
- Python爬蟲開發(二):整站爬蟲與Web挖掘Python爬蟲Web
- [爬蟲架構] 如何設計一個分散式爬蟲架構爬蟲架構分散式
- 使用java 爬蟲Java爬蟲
- 【Python學習】爬蟲爬蟲爬蟲爬蟲~Python爬蟲
- Python下用Scrapy和MongoDB構建爬蟲系統(2)PythonMongoDB爬蟲
- Python下用Scrapy和MongoDB構建爬蟲系統(1)PythonMongoDB爬蟲
- Web 端反爬蟲技術方案Web爬蟲
- 爬蟲普及,Web安全更需注意爬蟲Web
- 怎麼使用爬蟲爬蟲
- node爬蟲-使用puppeteer爬蟲
- Python爬蟲:手把手教你寫迷你爬蟲架構Python爬蟲架構
- Python爬蟲之路-chrome在爬蟲中的使用Python爬蟲Chrome
- 使用Golang快速構建WEB應用GolangWeb
- 構建header在python爬蟲中出錯怎麼解決?HeaderPython爬蟲
- 為爬蟲框架構建Selenium模組、DSL模組(Kotlin實現)爬蟲框架架構Kotlin
- 手把手教你寫網路爬蟲(2):迷你爬蟲架構爬蟲架構
- python網路爬蟲(14)使用Scrapy搭建爬蟲框架Python爬蟲框架
- 實用爬蟲-02-爬蟲真正使用代理 ip爬蟲
- Python爬蟲之路-selenium在爬蟲中的使用Python爬蟲
- 爬蟲:多程式爬蟲爬蟲
- [CareerCup] 10.5 Web Crawler 網路爬蟲Web爬蟲
- 爬蟲框架-scrapy的使用爬蟲框架
- 爬蟲-selenium的使用爬蟲
- Scrapy爬蟲框架的使用爬蟲框架
- 爬蟲使用代理是否安全爬蟲