文章标题

nodejs–简单爬虫

首先你需要掌握以下内容:

 1. 简单的JS基础
 2. 了解过函数式编程
 3. jquery选择器

本文的运行环境:

  1. windows10
  2. 已经安装好nodejs

有关nodejs的安装请自行百度,这里不做过多的介绍


正文

首先安装好以下模块

  • eventproxy
  • cheerio
  • async

(关于async我的代码有一个问题,之后会说明,请大神帮忙看下,告诉我为什么,谢谢)

首先写一个方法用来获取目标HTML文本

var http = require('http');
var async = require('async');
var cheerio = require('cheerio');
var url = require('url');
var eventproxy = require('eventproxy');

//指定网页URL
var urlAddress  = "http://tieba.baidu.com/f?kw=c%23&fr=home";
var down = function (url,callback){
    http.get(url,function(res){
        var data = "";
        //读取文件流
        //有关request的使用方式不懂的朋友可以去官网看看
        //https://github.com/mikeal/request
        res.on('data',function(chunk){
            data += chunk;
        });
        res.on('end',function(){
           callback(data);
        });
    }
    ).on('error',function(){
        callback(null)
    });
}

好了,上面的代码就算一个小小的爬虫了。(一根筋的小蜘蛛)

down(urlAddress,function(data){
    //判断下是否成功获取到HTML文本
    if(data){
        console.log(data);
    }else{
        console.log("error");
    }
});

以上的代码是down函数的调用示例,获取到HTML文本后直接输出,如果失败的输出error

下面我们就来使用下cheerio和eventproxy模块


//先抓取页面,然后分析出里面帖子的地址,存到数组里
var topicUrls = [];
//标题头
var urlAdd = "http://tieba.baidu.com";
//这里我们调用down方法,让小蜘蛛消化下HTML文本
//然后生下更多的小蜘蛛去爬更多的页面
down(urlAddress ,function(data){
    //和jquery一样的用法
    var $ = cheerio.load(data);
    //如果class包含.j_th_tit并且在a标签下则执行该函数
    $('a.j_th_tit').each(function (idx, element) {
        var $element = $(element);
        //利用url拼接标题头和获取到的链接
        //也可以写成 var href = urlAdd + $element.attr('href');
        var href = url.resolve(urlAdd,$element.attr('href'));
        //将链接放进数组里
        topicUrls.push(href);
    });
    //这里我们输出下获取到的链接数量
    console.log(topicUrls.length);

    var ep = new eventproxy();
    //循环数组并为每一个元素执行一次函数
    topicUrls.forEach(function(item){
       //获取链接的HTML文本
       down(item,function(data){           
           //添加html_load事件
           ep.emit('html_load',data);
       });
    });
    //添加计数器
    var time = 0;
    //after是当事件达到10次时执行
    ep.after('html_load',10,function(data){
        //循环数组
        data.forEach(function(data){
            var $2 = cheerio.load(data);
            var first = "";
            //读取第一条符合条件的文本
            $2('div.d_post_content').first().each(function (idx, element) {
                var $element = $(element);
                time = time + 1;
                first = time + ':' + $element.text();
            });
            //输出文本
            console.log(first);
        });
    });

});

贴出完整的代码

var http = require('http');
var async = require('async');
var cheerio = require('cheerio');
var url = require('url');
var eventproxy = require('eventproxy');

var urlAddress  = "http://tieba.baidu.com/f?kw=c%23&fr=home";
var down = function (url,callback){
    http.get(url,function(res){
        var data = "";
        res.on('data',function(chunk){
            data += chunk;
        });
        res.on('end',function(){
           callback(data);
        });
    }
    ).on('error',function(){
        callback(null)
    });
}
//先抓取页面,然后分析出里面帖子的地址,存到数组里
var topicUrls = [];
var urlAdd = "http://tieba.baidu.com";
down(urlAddress ,function(data){
    var $ = cheerio.load(data);
    $('a.j_th_tit').each(function (idx, element) {
        var $element = $(element);
        var href = url.resolve(urlAdd,$element.attr('href'));
        topicUrls.push(href);
    });
    console.log(topicUrls.length);

    var ep = new eventproxy();
    topicUrls.forEach(function(item){
       down(item,function(data){
           ep.emit('html_load',data);
       });
    });
    var time = 0;
    ep.after('html_load',10,function(data){
        data.forEach(function(data){
            var $2 = cheerio.load(data);
            var first = "";
            $2('div.d_post_content').first().each(function (idx, element) {
                var $element = $(element);
                time = time + 1;
                first = time + ':' + $element.text();
            });
            console.log(first);
        });
    });

});

以上就是一个简单的爬虫
里面用了一个并发事件,一次发出10条请求,个人觉得不妥,于是就用了ascyn,但是还不习惯异步思想,所以有一个问题无法解决。请大家看看,指点迷津

下面贴出代码

var http = require('http');
var async = require('async');
var cheerio = require('cheerio');
var url = require('url');
var eventproxy = require('eventproxy');

var urlAddress  = "http://tieba.baidu.com/f?kw=c%23&fr=home";
var down = function (url,callback){
    http.get(url,function(res){
        var data = "";
        res.on('data',function(chunk){
            data += chunk;
        });
        res.on('end',function(){
           callback(data);
        });
    }
    ).on('error',function(){
        callback(null)
    });
}
//先抓取页面,然后分析出里面帖子的地址,存到数组里
var topicUrls = [];
var urlAdd = "http://tieba.baidu.com";
down(urlAddress ,function(data){
    var $ = cheerio.load(data);
    $('a.j_th_tit').each(function (idx, element) {
        var $element = $(element);
        var href = url.resolve(urlAdd,$element.attr('href'));
        topicUrls.push(href);
    });
    console.log(topicUrls.length);

    var time = 0;
    //这里只执行了5次,我个人的想法是每次5条请求,最后一共执行
    //topicUrls.length条
    //我个人分析下觉得是执行完5次后,down函数结束了,顺带着把async也关了
    //但是异步的话应该async是独立的函数,不应该受到影响才对
    //请大家帮忙指点下
    async.forEachLimit(topicUrls,5,function(item, callback){
        down(item,function(data){
            var $ = cheerio.load(data);
            $('div.d_post_content').first().each(function (idx, element) {
                var $element = $(element);
                time = time + 1;
                console.log(time + ':' + $element.text());
            });
        });
    },function(err){
        console.log('错误:' + err);
    });

});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值