發現node可以爬蟲,正好我在找暑期實習,然后就使用node爬一下網站數據找實習。
准備工作
爬取目標網站
//加載http模塊
var http = require('http');
//目標網站,嘿嘿,這個網站有很多實習職位
var pageUrl = 'http://shixi.info/';
http.get(pageUrl, function(res) {
var html = '';
res.on('data', function(data) {
html += data;
});
res.on('end', function() {
console.log(html);
});
});
http的get請求一個目標網站,回調函數的參數是response,綁定兩個事件,一個'data'事件,會不斷觸發獲取數據,數據獲取完觸發’end‘ 事件。
爬到的的數據就是目標網站的html源代碼。
現在html代碼有了,我們該怎么解析這個呢?
解析html代碼
在這里我們使用cheerio模塊,是服務器端的html解析模塊,使用方法類型jQuery
var http = require('http');
var cheerio = require('cheerio');
var pageUrl = 'http://shixi.info/';
http.get(pageUrl, function(res) {
var html = '';
res.on('data', function(data) {
html += data;
});
res.on('end', function() {
//數據獲取完,執行回調函數
callback(html);
});
});
function callback(html) {
//使用load方法,參數是剛才獲取的html源代碼數據
var $ = cheerio.load(html);
var arrUrl = [];
//寫法和jQuery一模一樣,有沒有覺得很cool
$('article').each(function(index, element) {
var href = $(element).find('.entry-title a').attr('href');
arrUrl.push(href);
});
}
這樣我們就把目標頁面的每條招聘信息的網址存放進了一個數組,當然我們也可以通過對象字面量存一些其他數據,比如招聘信息的title,date等等。
可能有人會問,我只要網址干嘛?嘿嘿,因為JD是在詳情頁里面,不去爬詳情頁,我咋看JD。
並發請求
為演示方便:只獲取了職位title。
對arrUrl迭代,GET請求。因為是異步操作,所以在這里我們建一個count變量,每次完成一個操作count++,執行done函數,如果count值和arrUrl數組的長度相同,執行函數。
var count = 0;
var results = [];
function done() {
if (count == arrUrl.length) {
console.log('done');
}
}
arrUrl.forEach(function(item, index) {
http.get(item, function(res) {
var html = '';
res.on('data', function(data) {
html += data;
});
res.on('end', function() {
var $ = cheerio.load(html);
var title = $('.entry-title').text();
results[index] = {
url: item,
title: title
};
count++;
done();
});
});
});
使用express模塊讓數據響應到網頁
var express = require('express');
var app = express();
function done() {
if (count == arrUrl.length) {
//get 方法,第一個參數路徑,是一個route的作用。
//回調函數,參數分別是:請求,響應。
//監聽8888端口,瀏覽器打開 http://127.0.0.1:8888
app.get('/', function(req, res) {
res.send(JSON.stringify(results));
}).listen('8888', '127.0.0.1');
console.log('done');
}
}
瀏覽器打開 http://127.0.0.1:8888,就能看到我們爬的數據了。
當然我們也可以 對這些數據處理一下,返回到網頁的是html內容文本。
使用eventproxy模塊控制並發
剛才我們使用的是count變量,有些不夠優雅。這里我們引入eventproxy模塊。
var eventproxy = require('eventproxy');
//得到實例化對象ep
var ep = new eventproxy();
//after,第一個參數是事件名,第二個參數是事件的數量,回調函數的參數是list集合,
ep.after('subscribe', arrUrl.length, function(results) {
app.get('/', function(req, res) {
res.send(JSON.stringify(results));
}).listen('8888', '127.0.0.1');
console.log('done');
});
arrUrl.forEach(function(item, index) {
http.get(item, function(res) {
var html = '';
res.on('data', function(data) {
html += data;
});
res.on('end', function() {
var $ = cheerio.load(html);
var title = $('.entry-title').text();
//通知ep的subscribe事件,ep監測執行完的事件數量等於arrUrl.length,如果等於 執行回到函數。
ep.emit('subscribe', {
url: item,
title: title
});
});
});
結束
通過nodejs爬蟲的學習,學習到了http,express,cheerio,eventproxy的簡單使用。更了解到了node異步編程。