为了账号安全,请及时绑定邮箱和手机立即绑定

Nodejs,不一样的爬虫实践

2016.02.03 23:10 14080浏览

做前端以来,对我成长帮助最大的恐怕也就是各位大侠们的博客了,,慢慢的也在我心里种下了颗种子:我也要写博客!哪怕我文笔差,技术菜,难以望其项背,我也要追随大神们的脚步,写写博客,处处留香。摸爬滚打,终是成长;学习分享,与君共勉!小前端初学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来说,又走了一小步,也挺好玩的;马上就过年了,又要老一岁了啊,不过也很快就到春天了,祝大家猴年大吉,四季如春!

点击查看更多内容
59人点赞

若觉得本文不错,就分享一下吧!

评论

相关文章推荐

正在加载中
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消