Node.js爬取妹子图-async的使用

在上一篇中《Node.js爬取妹子图-crawler爬虫的使用》,主要介绍的crawler。之前在写《Node.js 2小时爬取驴妈妈8W+条旅游数据》时,使用的是node-schedule,做的定时任务,这样就可以不间断的爬取了。
这次在爬取妹子图使用的是async,这次的效率明显的提升了很多,感觉1分钟就爬取了37581条数据,再来8W条也是小case。
这里写图片描述
在上一篇《Node.js爬取妹子图crawler爬虫的使用》中的function downloadContent(i,c)方法,我卖了一个关子,这里就做说明,顺便介绍一下async
这里写图片描述
关于async这个,大家还是先看文档,https://caolan.github.io/async/。如果你在使用一个新东西之前,连看文档的心都没有,我不建议你使用了。
其实在《Node.js 批量下载图片》中,我就使用过async,只是当时没说。上次使用的是each,这次使用的是队列queue
妹子图中,一共有72页数据,2806个主题,37581张图片。
1.爬取2806个主题

// 浏览器访问一下之后就断掉,不要继续链接这个地址
router.get('/api/crawler/crawler', function(req, resq, next){
    var c = new Crawler({
        maxConnections : 10,
        retries: 5,
        // This will be called for each crawled page
        callback : function (error, res, done) {
            if(error){
                console.log(error);
            }else{
                var $ = res.$;
                console.log($("title").text(),'1');
            }
            done();
        }
    });

    c.queue([{
        uri: 'http://www.meizitu.com/a/more_1.html',
        jQuery: true,
        callback: function (error, res, done) {
            if(error){
                console.log(error);
            }else{
                var $ = res.$;
                var total_pag = 0;
                $('#wp_page_numbers li a').each(function(index,item){
                        if ($(item).text() == '末页') {
                            total_pag = $(item).attr('href');
                            var regexp = /[0-9]+/g;
                        total_pag = total_pag.match(regexp)[0]; // 总页数
                        }
                })
                var tempArray = [];
                var q = async.queue(function(task, callback) {
                    console.log('hello ' + task.name);
                    downloadContent(task.name,c); // 每个人物都会执行一个这个
                    callback();
                }, total_pag);
                q.drain = function() {
                    console.log('all items have been processed');
                };
                for (var i = 1; i <= total_pag; i ++) {
                       var item = {
                            name: i  // 队列中的每个人物都有个 name
                       }
                       tempArray.push(item);
                }
                // 添加进队列
                q.push(tempArray, function(err) {
                    console.log('finished processing item');
                });
                console.log(total_pag);  // 72
            }
            done();
        }
    }]);
})

// 分页下载
function downloadContent(i,c){
    var uri = 'http://www.meizitu.com/a/more_' + i + '.html';
    c.queue([{
        uri: uri,
        jQuery: true,
        callback: function (error, res, done) {
            if(error){
                console.log(error);
            }else{
                var $ = res.$;
                var meiziSql = '';
                $('.wp-item .pic a').each(function(index,item){
                        var href = $(item).attr('href'); // 获取路径uri
                    var regexp = /[0-9]+/g;
                    var artice_id = href.match(regexp)[0]; // 获取文章ID
                    var title = $(item).children('img').attr('alt');
                    title = title.replace(/<[^>]+>/g,""); // 去掉 <b></b> 标签
                    var src = $(item).children('img').attr('src');
                    var create_time = new Date().getTime();
                    if (href == 'http://www.meizitu.com/a/3900.html') {
                        title = title.replace(/'/g,''); // 这个的标题多了一个 单引号, mysql在插入的时候存在问题,所以这样处理了一下
                    } 
                    var values = "'" + artice_id + "'" + ',' 
                            + "'" + title + "'" + ',' 
                            +  "'" + href + "',"  
                            + "'" + src + "'" + ',' 
                            + "'" + create_time + "'";
                    meiziSql = meiziSql + 'insert ignore into meizitu_all(artice_id,title,href,src,create_time) VALUES(' + values + ');';
                })
                pool.getConnection(function(err, connection) {
                    if(err){
                        console.log('数据库连接失败',i);
                    }
                    connection.query(meiziSql,function (err, results) {
                        connection.release();
                        if (err){
                            console.log(err,i);
                        }else{
                            console.log('插入成功',i);
                        }
                    })
                })
            }
            done();
        }
    }]);
}

在写到这里的时候,突然想到了之前玩stm32的时候,跑ucos ii的时候,也有这个概念也有这个词task
首先获取页数,然后每页的爬取。
2.爬取37581张图片
这里写图片描述

router.get('/api/crawler/crawler2', function(req, resq, next){
    pool.getConnection(function(err, connection) {
        if(err){
            console.log('数据库连接失败');
        }
        connection.query('select * from meizitu_all',function (err, results) {
            connection.release();
            if (err){
                console.log('数据库查询失败');
            }else{
                var artices = results;
                var c = new Crawler({
                    maxConnections : 10,
                    retries: 5,
                    // This will be called for each crawled page
                    callback : function (error, res, done) {
                        if(error){
                            console.log(error);
                        }else{
                            var $ = res.$;
                            console.log($("title").text(),'1');
                        }
                        done();
                    }
                });
                var total_pag = artices.length;
                var tempArray = [];
                var q = async.queue(function(task, callback) {
                    console.log('hello ' + task.name);
                    download2(task.name,task.artice_id,c,task.index);
                    callback();
                }, total_pag);
                q.drain = function() {
                    console.log('all items have been processed');
                };
                for (var i = 0; i < total_pag; i ++) {
                       var href = artices[i].href;
                       var artice_id = artices[i].artice_id;
                       var item = {
                            name: href,  // 队列中,每个任务要有一个 name  其他字段可以自行添加
                            artice_id: artice_id,
                            index: i
                       }
                       tempArray.push(item);
                }
                q.push(tempArray, function(err) {
                    console.log('finished processing item');
                });
                console.log(total_pag);
            }
        })
    })
})
// 下载详情
function download2(name,artice_id,c,index){
    c.queue([{
        uri: name,
        jQuery: true,
        callback: function (error, res, done) {
            if(error){
                console.log(error);
            }else{
                var $ = res.$;
                var meiziSql = '';
                if ($('#picture p img').length != 0) {
                    $('#picture p img').each(function(index,item){
                            var pic_alt = $(item).attr('alt');
                            var pic_src = $(item).attr('src');
                        var create_time = new Date().getTime();
                        var values = "'" + artice_id + "'" + ',' 
                                + "'" + pic_alt + "'" + ',' 
                                +  "'" + pic_src + "',"  
                                + "'" + create_time + "'";
                        meiziSql = meiziSql + 'insert ignore into meizitu_detail(artice_id,pic_alt,pic_src,create_time) VALUES(' + values + ');';
                    })
                 }
                if ($('.postContent img').length != 0) {
                        $('.postContent img').each(function(index,item){
                            var pic_alt = $(item).attr('alt');
                            var pic_src = $(item).attr('src');
                        var create_time = new Date().getTime();
                        var values = "'" + artice_id + "'" + ',' 
                                + "'" + pic_alt + "'" + ',' 
                                +  "'" + pic_src + "',"  
                                + "'" + create_time + "'";
                        meiziSql = meiziSql + 'insert ignore into meizitu_detail(artice_id,pic_alt,pic_src,create_time) VALUES(' + values + ');';
                    })
                }
                if (meiziSql != '') {
                        pool.getConnection(function(err, connection) {
                        if(err){
                            console.log('数据库连接失败',index);
                        }
                        connection.query(meiziSql,function (err, results) {
                            connection.release();
                            if (err){
                                console.log(err,index,artice_id);
                            }else{
                                console.log('插入成功',index,artice_id);
                            }
                        })
                    })
                }
            }
            done();
        }
    }]);
}

先从数据库中取出,上一步存储的主题,然后加入队列任务爬取和存储。
这次感觉使用的队列之后,爬取效率大大的提升。

猜你喜欢

转载自blog.csdn.net/zhuming3834/article/details/79814609