Nodejs,不一样的爬虫实践
做前端以来,对我成长帮助最大的恐怕也就是各位大侠们的博客了,,慢慢的也在我心里种下了颗种子:我也要写博客!哪怕我文笔差,技术菜,难以望其项背,我也要追随大神们的脚步,写写博客,处处留香。摸爬滚打,终是成长;学习分享,与君共勉!小前端初学Nodejs,搭了个简单的博客,捉襟见肘,望大侠路过指导!好了,此处有广告之嫌,进入正题。
关于Nodejs的爬虫程序,百度一大把,是的,我也是百度到的,然后到github上看了看cheerio模块;乍一看,这不就是Jquery嘛,没想到Jquery都能牛到后端操作DOM了啊,恩。。。可以先这么认为和理解吧,因为cheerio确实可以像jquery操作DOM一样操作从远程爬取过来的页面;顿时邪念四起:我要把我喜欢的博客全抓到我的博客站点上去、我要不翻墙而是把谷歌抓过来访问。。。然后就有了我博客上的“爬呀爬”版块,都是爬取的国内顶尖的前端团队呕心沥血写的博客,,保留了作者信息和版权,当然,如果他们看到了,骂我一顿,叫我删掉,我肯定会屁颠屁颠删掉的;
还有就是怎么通过我的站点访问谷歌了,比如:http://www.famanoder.com?url=http://google.com的请求,我res.send(googleBody);恩 ,这样是可以的,可是问题在于:相对路径的资源返回404了,因为相对路径域名取的是我的站点,而我的站点没有对应的目录和资源,自然404了;这时cheerio可就很有用了,在res.send之前可以对body进行些DOM操作啊,貌似有点复杂啊,我正则还不行。。。为了让爬取过来的谷歌可以点击,链接没有404,还需要做一步,就是通过cheerio将所有相对路径补上http://www.famanoder.com?url=http://google.com,绝对路径补上http://www.famanoder.com?url=来将爬取的目标站点所有资源都通过我的博客站点请求;
很高兴,一个小小的爬虫让我我又知道了三个很好用的模块:request、superagent、cheerio;
request和superagent差不多,过年后做个横向的比较,争取进一步理解http模块;
先看看request怎么抓页面的吧,江湖中人不多废话了,看代码:
if (req.query.url) {
var iurl = decodeURIComponent(req.query.url);
var thaturl = url.parse(iurl).protocol +url.parse(iurl).host;
var body=[],size=0;
request.get({
url: iurl,
headers: {
}
})
.on('response', function (response) {
res.set(response.headers);
response.setEncoding='utf8';
response.on('data',function(chunk){
body.push(chunk);
size+=chunk.length;
});
})
.on('error', function (err) {
console.log(err);
})
.on('end',function(){
//buffer 防止丢包的情况,如果数据过多,会抓不全的。。。。。
var data = Buffer.concat(body , size);
var html = data.toString();
var $=cheerio.load(html);
//只是个栗子,具体情况还会要url.parse解析所有href、src再处理
$('a').each(function(){
$(this).attr('href','http://famanoder.com?url='+$(this).attr('href'));
});
res.write($('html,body').html());
})
//.pipe(res);
}
除了丢包,一般不会有什么问题了,可能就是unicode中文的乱码了,也有很多模块可以处理,不过用JS弄也不错,谢谢某大侠的代码,找半天了,值得收藏:
function reconvert(str){
str = str.replace(/(\\u)(\w{4})/gi,function($0){
return (String.fromCharCode(parseInt((escape($0).replace(/(%5Cu)(\w{4})/g,"$2")),16)));
});
str = str.replace(/(&#x)(\w{4});/gi,function($0){
return String.fromCharCode(parseInt(escape($0).replace(/(%26%23x)(\w{4})(%3B)/g,"$2"),16));
});
return str;
}
对了,抓取来的body是不能直接操作的,不信试一试,不用cheerio而是直接toString再replace什么的,都是无用功;
好吧,到这我一口气爬取了上百篇大神们的博客,,还是有些繁琐的,巴拉巴拉,我想还是弄个定时任务吧,每天到点就爬一页,取最新的留下;这里也有两个模块供选择:schedule、later,还是下次做个横向的比较吧,期待。schedule这个单词在学校时就没写对过,今天终于写对了,原谅我,又掉底子了。。。看看定时任务吧:
var registTask=function(hour,minute,taskname,fn){
var rule = new schedule.RecurrenceRule();
//每天这个时刻定时执行任务
rule.dayOfWeek = [0, new schedule.Range(1, 6)];
rule.hour = hour;
rule.minute = minute;
var j = schedule.scheduleJob(rule, function(){
console.log("开始爬取:"+taskname);
fn&&fn();
});
}
registTask(23,30,'TaoBaoFED',function(){
getTaoBaoFEDBokes(1);
//呵呵,每天23:30爬一页
});
差不多这就是“爬呀爬”这个小玩意,对于一个业余的noder来说,又走了一小步,也挺好玩的;马上就过年了,又要老一岁了啊,不过也很快就到春天了,祝大家猴年大吉,四季如春!
共同学习,写下你的评论
评论加载中...
相关文章推荐