Nodejs相關依賴模塊介紹
Nodejs的優勢這里就不做介紹啦,這年頭相信大家對它也不陌生了。這里主要介紹一下用到的第三方模塊。
- async:js代碼中到處都是異步回調,很多時候我們需要做同步處理,使用async可以大大簡化我們的同步處理的任務(沒有它的時候,可能要用遞歸去處理異步問題了)。
- jsdom:一個 W3C DOM 的 JS 實現。用這玩意相當犀利,它不僅可以將文檔解析成 DOM,而且,你還可以用 YUI 或着 jQuery 去操作生成的 DOM。這在從頁面中提取數據時格外有用。這次采集17173的游戲排行數據就是用它結合jQuery去做的。
- colors:這個主要是便於我們從終端中輸出不同顏色的信息用的,它的用法相當簡單,console.log的時候直接在字符串后附加相關的顏色信息就可以了。
17173游戲排行頁面分析
17173游戲排行頁面:http://top.17173.com/index-0-0-0-0-0-0-0.html
我們要抓取它的排行,游戲名,熱度值和測試狀態信息,為了保存方便,直接將抓取的這些信息以CSV格式文件保存。
排行信息總共有63頁,使用Chrome調試發現,請求不同頁的數據時,發送的是HTTP POST請求,不同的頁數通過page參數傳遞的,參數t可以忽略,主要是清瀏覽器緩存用的,如下圖所示:

使用Chrome查看html結構,我們要抓取的數據在ul.ph-bd-list li中,如下圖所示:

在前端獲取游戲排行列表的Html信息時,使用jQuery,$('.ph-bd-list li')可以非常方便的定位到列表信息,如果在服務端也能使用這種方式提取信息豈不爽哉,如下圖所示:

Nodejs在服務端使用jQuery采集游戲排行信息
首先要解決的問題是,如何使用nodejs發送post請求,並從服務器返回的信息中得到html。
完成這件事並不難,查看一下nodejs,http模塊相關的文檔,文檔中剛好有個示例,幾乎可以直接拿來用,需要注意的是,nodejs接收服務端返回的數據時,是以數據塊的形式接收的,我們需要將這些數據塊,拼裝成完整的數據,代碼如下:
// 構造請求信息 var options = { hostname: 'top.17173.com', port: 80, path: '/index-0-0-0-0-0-0-0.html?page=' + index, method: 'POST' }; var req = http.request(options, function(res) { var html = ''; res.setEncoding('utf8'); // 拼裝數據 res.on('data', function (chunk) { html += chunk; }); res.on('end', function () { parseHtml(html, callback); // 對html做解析處理 }); }); req.on('error', function(e) { console.log(('請求列表頁失敗: ' + e.message).red); }); // write data to request body req.write('data\n'); req.write('data\n'); req.end();
接下來需要對html做處理,我們需要用jsdom將html解析為DOM,並跟jQuery結合,確保在服務端能夠使用jQuery操作DOM,為了便於使用,我把這些操作做了簡單的封裝,核心代碼如下:
var jsdom = require('jsdom').jsdom , fs = require('fs') , jquery = fs.readFileSync("./jquery.js", "utf-8"); /** * 使用jsdom將html跟jquery組裝成dom * @param {[type]} html 需要處理的html * @param {Function} callback 組裝成功后將html頁面的$對象返回 * @return {[type]} [description] */ function makeDom(html, callback) { jsdom.env({ html: html, src: [jquery], done: function (errors, window) { var $ = window.$; callback(errors, $); window.close(); // 釋放window相關資源,否則將會占用很高的內存 } }); }
借助上面封裝的代碼,現在我們就可以非常方便的使用jQuery在服務端操作html了,尤其是使用jQuery提取信息,示例代碼如下:
makeDom(html, function (errors, $) { // 游戲排行列表 var gameList = $('.ph-bd-list li'); // 獲取每一個游戲信息 gameList.each(function () { var li = $(this); // 游戲信息,各個信息間使用逗號拼接 var gameInfo = ''; // 游戲排名 gameInfo += li.find('span.ttime').text() + ','; // 游戲名稱 gameInfo += li.find('span.game-name a').text() + ','; // 熱度值 gameInfo += li.find('span.type').text() + ','; // 測試狀態信息 gameInfo += $.trim(li.find('span.jhm').text()); // 輸出抓取的信息 console.log(gameInfo.white); // 將游戲信息保存到文本文件 fs.appendFileSync('17173_game_rank.csv', gameInfo + '\r\n'); }); console.log(('第' + index + '頁抓取完畢').yellow); // 設置抓取下一頁 index++; // 執行回調,通知async本次抓取結束 callback(); });
最終程序跑起來的效果

代碼也來一份吧
代碼加注釋也就100多行,不多,也不復雜,希望能給用到的人帶來點思路。
下載后,先使用npm install命令安裝依賴模塊,然后使用node app.js執行即可。
jsdom在windows上的安裝貌似還有些麻煩,大家參考這篇文章自行解決一下吧:http://www.swordair.com/blog/2012/05/901/
