边作边学效率更高,爬虫是node的适用场景之一,关于爬虫的另外一篇文章
为了验证“简书上,经验总结、资料归集类技术文章更容易上热榜”的猜测,能够作一个爬虫:爬取简书程序员专题热门文章前999篇,统计每篇文章的代码块数量(为何是统计代码块数量,对于人来讲,经过一篇文章的标题内容来判断文章的类型是一件垂手可得的事,然而对于计算机来讲,这倒是一件困难的事情,这已经属于人工智能的范畴了。然而获取文章的代码块数量对于计算机来讲就容易得多了,能够认为,代码块为0或者较少的文章,属于经验类文章,代码块数量较多的文章若是不是资料归集的话,多半就属于谈源码实现的了)javascript
ajax请求,须要使用chrome dev tools,拉到底部还能加载更多:java
//order_by=likes_count 表示按照热门进行排序
//page是分页参数,每页9条,咱们能够经过改变page=0~100来拉取900篇文章
http://www.jianshu.com/collections/16/notes?order_by=likes_count&page=2复制代码
下一步经过这个连接拉取列表数据node
/** - 建立promise */
Seek.prototype.createPromise = function(i) {
var options = {
url: 'http://www.jianshu.com/collections/16/notes?order_by=likes_count&page=' + i,
type: 'get'
}
return new Promise(function(resolve, reject) {
options.callback = function(data, _setCookie) {
resolve(data);
}
request(options, null);
});
}复制代码
能够建立一个promise对象来发起request请求(request的封装就不贴出来了,实验证实,代码块太多的文章不容易上热榜~~)jquery
起初个人作法是同时建立拉取1~100页数据的100个promise对象,同时异步的发起100个request请求,然而这样的作法会有几十个请求请求失败(兴许是简书那边作了限制),因此,仍是耐心点,每次发起5个请求,直到100页都请求成功git
/** * 递归的请求,每次并发的请求5个 */
Seek.prototype.seek = function(callback) {
var self = this;
times++;
var ot = times;
var promise = Promise.all([
self.createPromise(times),
self.createPromise(++times),
self.createPromise(++times),
self.createPromise(++times),
self.createPromise(++times)
]);
promise.then(function(result) {
console.log("seekList totals:" + times);
pages = pages.concat(result);
if (times < totalPage) {
self.seek(callback);
} else {
callback(pages);
}
});
}复制代码
拿到全部的列表数据以后,就能够使用cheerio库来分析列表页面,抓取文章详情连接(在这一步以前你一样须要使用chrome dev tools工具分析页面结构)程序员
/** * 使用cheerio载入列表页面 */
Analyse.prototype.load = function(data, i) {
return new Promise(function(resolve, reject) {
var $ = cheerio.load(data);
var pages = [];
var els = $('.article-list li');
if(els.length === 0) {
console.warn('load error page:' + i );
resolve([]);
}
els.each(function(index) {
if ($(this).attr('class') === 'have-img') {
pages.push($(this).children('a').attr('href'));
} else {
pages.push($(this).children('div').children('.title').children('a').attr('href'));
}
if(index === els.length - 1) {
resolve(pages);
}
});
});
}复制代码
<code></code>
标签,统计此标签出现的数量就能够了
/** * 建立promise */
Seek.prototype.createPromise = function(url) {
var options = {
url: 'http://www.jianshu.com' + url,
type: 'get'
}
return new Promise(function(resolve, reject) {
options.callback = function(data, _setCookie) {
var $ = cheerio.load(data);
//页面标题
var title = $('h1.title').text();
//代码块数量
var codes = $('code').length;
if(codes === 0) {//代码块为0的总数
zeroCount++;
} else if(codes <= 10) {//代码块为<=10的总数
oneToTen++;
} else if(codes <= 20) {//代码块<=20的总数
elToTwo++;
} else {//代码块>20的总数
beyondTwo++;
}
resolve({
title: title,
codes: codes
});
}
request(options, null);
});
}复制代码
下一篇文章讲 Node 爬虫进阶,敬请关注github
补充说明:代码大半年前些的,简书的接口和页面结构已经作了改版,可能抓取不到想要的结果,若是感兴趣,能够按照思路和步骤改造如今的代码,本身动手丰衣足食ajax