想要自動從網頁抓一些資料或者想把一坨從什麼部落格上拉來的資料轉成一種有結構的資料?
居然沒有現成的API可以取資料?!!! !@#$@#$…
沒關係 網頁抓取可以解決。
什麼是網頁抓取? 你可能會問。。。
網頁抓取是以程式設計的方式(通常不用瀏覽器參與)檢索網頁的內容並從中提取資料的過程。
本文,小編會給大家展示一套強大的抓取工具,可以快速的對網面進行抓取,而且容易上手,它是由javascript 和node.js實現的。
最近我需要爬一些大數量(謙虛的說)的頁面,然後分析它們從中找到一些規律。 你知道,實在太長時間沒有幹過種事了。。。這麼說吧, 手頭基本上是沒有現成的工具可以用了。。
我必須承認我實在太喜歡node.js了。 Node.js是一個用來脫離瀏覽器寫javascript程式的框架。 在Atwood’s 定律的指引下, node.js有了一套很強大的工具來幫助大家開發網路程式。你不光可以用node.js來開發webserver/websocket的程式碼, 我發現它還可以滿足我一些日常的指令碼需要。 所以我開始尋找node.js在網頁抓取方面的現成庫或工具, 果然,我找到了 Cheerio. Cheerio 是一個Node.js的庫, 它可以從一坨html的片斷中構建DOM結構,然後提供像jquery一樣的css選擇器查詢。
太好了! 因為,在這個世界上CSS和CSS驅動的樣式連結串列幾乎是唯一的網頁組織方式。(CSS乾的好!)最近人們往往使用CSS class風格的方式來製作各種結構的網頁。別誤解我,這個並不是解決問題的金鑰匙,我依然要處理大量的網頁,大部分是雜亂無章的。 但是對我來說 CSS選擇器提供一個強大快捷而簡單工具,從html中進行有效的的資料識別。 我典型的網頁抓取流程是這樣的, 首先用firebug或chrome開發者工具分析一下目標網頁的結構。主要關注的是我感興趣的資料即目標資料的css選擇器。 接下來就是用node.js搞起了。
如果你沒有安裝node.js或者很久沒有升級了, 那麼從這裡下載。 安裝程式不僅會安裝node.js本身,還會裝一個叫做npm的node 工具包管理器,npm可以用來快速下載並安裝node.js的庫。 這果我們用npm來安裝Cheerio這個庫。 執行以下這條命令。
1
|
npm install cheerio |
一旦Cheerio安裝完成, 我們就可以開始工作了。 首先讓我們來看一段javascript程式碼 這段程式碼可以下載任意一個網頁的內容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
var http = require( "http" );
// Utility function that downloads a URL and invokes // callback with the data. function download(url, callback) {
http.get(url, function (res) {
var data = "" ;
res.on( 'data' , function (chunk) {
data += chunk;
});
res.on( "end" , function () {
callback(data);
});
}).on( "error" , function () {
callback( null );
});
} |
這段程式碼可以非同步下載任意的URL (通過 HTTP GET方法), 而且在完成下載的時候,它會呼叫回撥函式並把下載的內容當做引數傳進去。接下的一段程式碼可以下載任意一個網頁並將其內容輸出到控制檯。
注意: 請大家從原始碼中引用download.js 只要簡單的遠行如下程式碼。
1
|
node download.js |
讓我們詳細看一下程式碼。
1
2
3
4
5
6
7
8
|
download(url, function (data) {
if (data) {
console.log(data);
}
else console.log( "error" );
}); |
這段程式碼會從指定的url下載內容並把內容列印到控制檯。 現在我們已經有了可以從網頁下載的內容的方法, 接下來就看Cheerio如何去提取我們感興趣的資料了。
在實際操作前,我們還要做一點研究和實驗,以幫助我們理解目標網頁的佈局結構, 這樣就可提取出人感興趣的內容了。 在這個具體的例子裡, 我們試圖把這些url裡的主要的圖片取出來。 我們可以先用瀏覽器開啟這些網頁,然後找到一個可以定位到這些圖片的方法, 你可以用chrome開發者工具 或直接看原始碼(比較難)可以具體的分離定位這些圖片,明白了麼? 讓我們來看程式碼吧。
注意: 請引用 squirrel.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
var cheerio = require( "cheerio" );
download(url, function (data) {
if (data) {
//console.log(data);
var $ = cheerio.load(data);
$( "div.artSplitter > img.blkBorder" ). each ( function (i, e) {
console.log($(e).attr( "src" ));
});
console.log( "done" );
}
else console.log( "error" );
}); |
引入cheerio模組後, 我們可以用之前寫好的download方法下載目標網頁的內容。 一旦我們有了資料, cheerio.load方法就會把HTML內容解析成DOM物件 並且可以像jquery css選擇器查詢那樣對這個DOM進行篩選,(注意:我把這個變數叫做$這樣就更像jquery了)。在目標網頁,我注意到這些圖片所在的div都有一個叫做 “artSplitter”的class, 而且這些圖片本身都有一個叫做”blkBorderf”的class。 為了能將它們唯一的找到,我寫了一條css選擇器查詢語句
1
|
$( "div.artSplitter > img.blkBorder" )
|
這個語句會返回一個圖片物件列表。 然後我們用each方法遍歷這些圖片然後把每一個圖片的src列印出來。效果還不錯。。。 我們再來看另外一個例子, 請引用 echo.js 原始碼。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
var cheerio = require( "cheerio" );
download(url, function (data) {
if (data) {
// console.log(data);
var $ = cheerio.load(data);
$( "article" ). each ( function (i, e) {
var link = $(e).find( "h2>a" );
var poster = $(e).find( "username" ).text();
console.log(poster+ ": [" +link.html()+ "](" +link.attr( "href" )+ ")" );
});
}
}); |
在這個栗子裡, 目標是echojs.com。 我想把這個網頁上所有文章的連結抓取並以markdown的格式列印出來。 首先我們用以下的語句把所有的artical節點都找到
1
|
$( "article" )
|
然後遍歷所有的節點,找到在h2下的a標籤 用以下的語句
1
|
var link = $(e).find( "h2>a" );
|
同樣,我可以用以下語句找到文章作者的名字
1
|
var poster = $(e).find( "username" ).text();
|
希望你能從這篇關於node.js和chreerio的文章中得到一些快樂吧。 請大家移步 Cheerio documentation 獲取列多的資訊。
雖然它可能不是適用於所有大型的網頁抓取,但它絕對是一個強大的工具, 尤其對於我們前端javascript jquery的開發來說。
原文地址: