ep.after('BlogArticleHtml',pageUrls.length*20,function(articleUrls){ // 当所有 'BlogArticleHtml' 事件完成后的回调触发下面事件 // 控制并发数 var curCount = 0; var reptileMove = function(url,callback){ //延迟毫秒数 var delay = parseInt((Math.random() * 30000000) % 1000, 10); curCount++; console.log('现在的并发数是', curCount, ',正在抓取的是', url, ',耗时' + delay + '毫秒'); superagent.get(url) .end(function(err,sres){ // sres.text 里面存储着请求返回的 html 内容 var $ = cheerio.load(sres.text); // 收集数据 // 拼接URL var currentBlogApp = url.split('/p/')[0].split('http://www.cnblogs.com/')[3], appUrl = "http://www.cnblogs.com/mvc/blog/news.aspx?blogApp="+ currentBlogApp; // 具体收集函数 personInfo(appUrl); }); setTimeout(function() { curCount--; callback(null,url +'Call back content'); }, delay); }; // 使用async控制异步抓取 // mapLimit(arr, limit, iterator, [callback]) // 异步回调 async.mapLimit(articleUrls, 5 ,function (url, callback) { reptileMove(url, callback); }, function (err,result) { // 4000 个 URL 访问完成的回调函数 // ... }); });
根据重新拼接而来的 URL ,再写一个具体的 personInfo(URL) 函数,具体获取我们要的昵称、园龄、粉丝数等信息。
这样,我们把抓取回来的信息以 JSON 串的形式存储在 catchDate 这个数组当中,
node index.js 运行一下程序,将结果打印出来,可以看到中间过程及结果:
至此,第三步就完成了,我们也收集到了4000条我们想要的原始数据。
Step.3 分析 展示
本来想将爬来的数据存入 mongoDB ,但因为这里我只抓取了4000条数据,相对于动不动爬几百万几千万的量级而言不值一提,故就不添加额外的操作 mongoDB 代码,专注于爬虫本身。
收集到数据之后,就想看你想怎么展示了,这里推荐使用 Highcharts 纯JS图表库去展示我们的成果。当然这里我偷懒了没有做,直接用最原始的方法展示结果。
下面是我不同时间段爬取,经过简单处理后的的几张结果图:
(结果图的耗时均在并发量控制为 5 的情况下)
后记
OK,至此,整个爬虫就完成了,其实代码量很少,我觉得写爬虫更多的时间是花在在处理各类问题,分析页面结构。
完整的爬虫代码,在我的github上可以下载。如果仍有疑问,可以把代码 down 到本地,重新从文章开头对照代码再实践一次,相信很多问题会迎刃而解。
因为代码开源,本着负责任的心态,希望大家可以照着代码写写其他网站的爬虫,如果都拿cnblog来爬,服务器可能会承受不住的:)
参考文章:《Node.js 包教不包会》。
原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。