4

上一篇文章:nodejs微信公众号开发——8.群发消息,介绍了高级群发接口的实现,并通过一个简单例子加以说明。本节的内容可能和微信公众号开发本身关系不大,只是我小项目中涉及到的内容,知识点包含nodejs爬虫和定时模块。(项目github地:https://github.com/Panfen/wem... )

1. nodejs网络爬虫

爬虫是自动获取网页内容的一个有效工具。虽然爬虫程序用Python开发的比较多,用nodejs也是一种不错的选择。我们以爬取飘花电影网为目标,爬取最近三天上线的电影,获取其电影名称电影海报图片电影详情页网页链接ftp下载链接的属性。整合成微信推送的内容。

2.爬虫基本操作

2.1 使用request模块来获取网页内容

request是一个简化HTTP请求操作的模块,功能强大且使用简单,通过GET方法来获取某个URL的内容:

var request = require('request');

var URL = 'http://www.piaohua.com/';

request.get(URL,function(err,res,body){
    if(!err && res.statusCode == 200){
        //输出网页内容
        console.log(body);
    }else{
        console.log('failed to crawl the website!');
    }
});

图片描述

当然,我们也采用http模块来获取数据:

var request = require('request');

var URL = 'http://www.piaohua.com/';

http.get(URL,function(res){
    var html = '';

    res.on('data',function(data){
        html += data;
    });

    res.on('end',function(){
        console.log(html);   //输出网页内容
    });
}).on('error',function(){
    console.log('failed to crawl the website!');
});

所得结果也是一样的,对比发现使用request的确更为简洁。

2.2 使用cheerio模块来提出网页数据

通过request获取到的是一堆网页代码,我们真正想要的数据跻身于这堆代码中。cheerio是一个jQuery Core的子集,其实现了jQuery Core中浏览器无关的DOM操作API。可以使用与jquery一样的语法来处理元素。

var cheerio = require('cheerio');

...

if(!err && res.statusCode == 200){
    var $ = cheerio.load(body);
    var movieList = $('#iml1').children("ul").first().find('li');
    var myMovieList = [];

    movieList.each(function(item){
        var time = $(this).find('span font').html() ? $(this).find('span font').html() : $(this).find('span').html();
        //筛选最近三天的电影
        if((new Date() - new Date(time)) < 259200000){
            var dom = $(this).find('a').first();
            var link = URL + $(dom).attr('href');
            var img = $(dom).find('img').attr('src');
            var name = $(dom).find('img').attr('alt').substr(22).replace('</font>','');
            
            var movie = {
                name:name,
                img:img,
                link:link,
                time:time,
            }
            myMovieList.push(movie);
        };
    });
    console.log(myMovieList);
}

图片描述

这里我们已经成功获取了最近三天电影的对象数组,信息包含了电影名称封面图片详情链接上线时间,和我们预期的要求还差了一个属性:ftp下载链接ftp下载链接在详情页面里面,所以我们需要进一步爬取信息。

if((new Date() - new Date(time)) < 259200000){
    var dom = $(this).find('a').first();
    var link = URL + $(dom).attr('href');
    var img = $(dom).find('img').attr('src');
    var name = $(dom).find('img').attr('alt').substr(22).replace('</font>','');
    getftpLink(link,function(ftp){
        var movie = {
            name:name,
            img:img,
            link:link,
            time:time,
            ftp:unescape(ftp.replace(/;/g,'').replace(/&#x/g, "%u"))  //Unicode转中文
        }
        myMovieList.push(movie);
    });                
};

getftpLink函数用以根据详情页链接link获取下载ftp:

function getftpLink(link,callback){
    request.get(link,function(err,res,body){
        if(!err && res.statusCode == 200){
            var $ = cheerio.load(body);
            var ftp = $('#showinfo').find('table tbody tr td a').html();
            callback(ftp);
        }
    });
}

图片描述

是不是很棒?拿到ftp可以直接用迅雷下载啦。

3. 爬虫定时操作

3.1 使用cron模块来定时执行任务

var cronJob = require('cron').CronJob;

var job = new cronJob('f1 f2 f3 f4 f5 f6',function(){
    //do something
});

f1 f2 f3 f4 f5 f6用以控制时间的选项,其中f1表示秒钟,f2表示分钟,f3表示小时,f4表示一个月中的第几日,f5表示月份,f6表示一个星期中的第几天。各部分的取值含义如下(以f1为例):

  • 当值为 * 时,表示每秒执行一次;
  • 当值为a-b时,表示从第a到第b秒这段时间内执行一次;
  • 当值为*/n时,表示每隔n秒执行一次;
  • 当值为a-b/n时,表示从第a到第b秒这段时间内每隔n秒执行一次;
var cronJob = require('cron').CronJob;

var job = new cronJob('00 30 11 * * *',function(){
     request.get(URL,function(err,res,body){
         ...
     });
});

这里表示的是每天中午11:30执行一次爬虫操作,获取推送图文的素材。


芒果屋里的猫
2.3k 声望363 粉丝

同步 -> 异步 -> 回调