爬取 CNode(https://cnodejs.org/) 社區首頁的標題和詳情頁的第一條評論,以及評論的做者,做者積分,最後以json格式打印html
注意:不少網站有併發鏈接數的限制,因此當請求發送太快的時候會致使返回值爲空或報錯。node
安裝依賴 express superagent cheerio eventproxyjquery
$ npm install express superagent cheerio eventproxy --save
新建app.js 抓取全部的urlexpress
// 引入依賴 var express = require('express'); var eventproxy = require('eventproxy'); var superagent = require('superagent'); var cheerio = require('cheerio'); var app = express(); // url 模塊是 Node.js 標準庫裏面的 var url = require('url'); var cnodeUrl = 'https://cnodejs.org/'; app.get('/', function(req, res, next) { // 用 superagent 去抓取 https://cnodejs.org/ 的內容 superagent.get(cnodeUrl) .end(function(err, sres) { if (err) { return next(err); } // sres.text 裏面存儲着網頁的 html 內容,將它傳給 cheerio.load 以後,就能夠獲得一個實現了 jquery 接口的變量,咱們習慣性地將它命名爲 `$` // 剩下就都是 jquery 的內容了 var $ = cheerio.load(sres.text); var topicUrls = []; // 獲取全部連接 $('#topic_list .topic_title').each(function(index, elem) { var $element = $(elem); // url.resolve 來自動推斷出完整 url var href = url.resolve(cnodeUrl, $element.attr('href')); topicUrls.push(href); }); res.send(topicUrls); }); }); app.listen(3000, function (req, res) { console.log('app is running at port 3000'); });
運行node app.js
npm
var ep = new eventproxy(); ep.all('data1_event', 'data2_event', 'data3_event', function (data1, data2, data3) { var html = fuck(data1, data2, data3); render(html); }); $.get('http://data1_source', function (data) { ep.emit('data1_event', data); }); $.get('http://data2_source', function (data) { ep.emit('data2_event', data); }); $.get('http://data3_source', function (data) { ep.emit('data3_event', data); });
ep.all('data1_event', 'data2_event', 'data3_event', function (data1, data2, data3) {});
json
這一句,監聽了三個事件,分別是 data1_event
, data2_event
, data3_event
,每次當一個源的數據抓取完成時,就經過 ep.emit()
來告訴 ep
本身,某某事件已經完成了。數組
當三個事件未同時完成時,ep.emit()
調用以後不會作任何事;當三個事件都完成的時候,就會調用末尾的那個回調函數,來對它們進行統一處理。併發
// 引入依賴 var express = require('express'); var eventproxy = require('eventproxy'); var superagent = require('superagent'); var cheerio = require('cheerio'); // url 模塊是 Node.js 標準庫裏面的 var url = require('url'); var app = express(); var ep = new eventproxy(); // 獲得一個 eventproxy 的實例 var cnodeUrl = 'https://cnodejs.org/'; app.get('/', function(req, res, next) { // 用 superagent 去抓取 https://cnodejs.org/ 的內容 superagent.get(cnodeUrl) .end(function(err, sres) { if (err) { return next(err); } // sres.text 裏面存儲着網頁的 html 內容,將它傳給 cheerio.load 以後,就能夠獲得一個實現了 jquery 接口的變量,咱們習慣性地將它命名爲 `$` // 剩下就都是 jquery 的內容了 var $ = cheerio.load(sres.text); var topicUrls = []; // 獲取全部連接 $('#topic_list .topic_title').each(function(index, elem) { var $element = $(elem); // url.resolve 來自動推斷出完整 url var href = url.resolve(cnodeUrl, $element.attr('href')); topicUrls.push(href); }); // 命令 ep 重複監聽 topicUrls.length 次(在這裏也就是 40 次) `topic_html` 事件再行動 ep.after('topic_html', topicUrls.length, function(topics) { // topics 是個數組,包含了 40 次 ep.emit('topic_html', pair) 中的那 40 個 pair topics = topics.map(function(topicpair) { var topicUrl = topicpair[0]; var topicHtml = topicpair[1]; var $ = cheerio.load(topicHtml); return ({ title: $('.topic_full_title').text().trim(), href: topicUrl, comment: $('.reply_content').eq(0).text().trim(), }); }); res.send(topics); }) topicUrls.forEach(function(topicUrl) { superagent.get(topicUrl) .end(function(uerr, ures) { console.log('success:' + topicUrl); ep.emit('topic_html', [topicUrl, ures.text]); }); }); }); }); app.listen(3000, function (req, res) { console.log('app is running at port 3000'); });