NodeJS制作爬虫全过程(续)


Posted in NodeJs onDecember 22, 2014

书接上回,我们需要修改程序以达到连续抓取40个页面的内容。也就是说我们需要输出每篇文章的标题、链接、第一条评论、评论用户和论坛积分。

如图所示,$('.reply_author').eq(0).text().trim();得到的值即为正确的第一条评论的用户。

{<1>}

NodeJS制作爬虫全过程(续)

在eventproxy获取评论及用户名内容后,我们需要通过用户名跳到用户界面继续抓取该用户积分

var $ = cheerio.load(topicHtml);

//此URL为下一步抓取目标URL

var userHref = 'https://cnodejs.org' + $('.reply_author').eq(0).attr('href');

userHref = url.resolve(tUrl, userHref);

var title = $('.topic_full_title').text().trim().replace(/\n/g,"");;

var href = topicUrl;

var comment1 = $('.reply_content').eq(0).text().trim();

var author1 = $('.reply_author').eq(0).text().trim();

//传递参数到下一次并发抓取

ep.emit('user_html', [userHref, title, href, comment1, author1]);

在eventproxy这一次中,我们要找到score是放在哪里(class="big")。

{<2>}

NodeJS制作爬虫全过程(续)

找到classname就好办了,我们先试着把结果输出一下

var outcome = superagent.get(userUrl)

    .end(function (err, res) {

        if (err) {

            return console.error(err);

        }

        var $ = cheerio.load(res.text);

        var score = $('.big').text().trim();

        console.log(user[1]);

        console.log(user[2]);

        console.log(user[3]);

        console.log(user[4]);

        console.log($('.big').text().trim());

        return ({

            title: user[1],

            href: user[2],

            comment1: user[3],

            author1: user[4],

            score1: score

        });

    });

});

运行程序,这段代码得到的结果。

{<3>}

NodeJS制作爬虫全过程(续)

但是问题来了,我们在.end()的回调函数中能正确输出结果,但是不能正确的输出outcome。仔细一看,需要输出的outcome是一个Request对象。这是因为粗心犯的错的,.end()函数并不会传递返回值给Request对象,需要将结果返回到上一层(users)。

//find userDetails

ep.after('user_html', topicUrls.length, function(users){

    users = users.map(function(user){

        var userUrl = user[0];

        var score;

        superagent.get(userUrl)

            .end(function (err, res) {

                if (err) {

                    return console.error(err);

                }

                //console.log(res.text);

                var $ = cheerio.load(res.text);

                score = $('.big').text().trim();

            });

        return ({

            title: user[1],

            href: user[2],

            comment1: user[3],

            author1: user[4],

            score1: score

        });

    });

把users好好地输出发现除了score1其他是正确值。仔细调试发现,程序是先进行了console.log(),然后再进行.map()。更准确地说,在.map()函数内,.get()的回调函数并没有执行完赋值score,return 返回值就进行了。这就是回调函数的异步,而外层的同步操作是不会等待回调函数做完操作的。

{<4>}

NodeJS制作爬虫全过程(续)

我的做法就是eventproxy再emit一层消息,伴随着消息把需要的数据一起传递给接收消息操作.after(),只有当消息全部接收完毕,再打印出传递的参数(结果)。

score = $('.big')text().trim();

//新添加

ep.emit('got_score', [user[1], user[2], user[3], user[4], score]);

.....

ep.after('got_score', 10, function(users){

console.log(users);

});

{<6>}

NodeJS制作爬虫全过程(续)

这个问题解决了,但score1的数值好像太大了点吧。再一看,原来class='big'有两个,用户的话题收藏也是属于这个class。我们得通过cheerio的.slice( start, [end] )来切取第一个元素,即将score 修改为 score = $('.big').slice(0).eq(0).text().trim();。正确结果如图。

{<7>}

NodeJS制作爬虫全过程(续)

NodeJs 相关文章推荐
基于promise.js实现nodejs的promises库
Jul 06 NodeJs
Nodejs Post请求报socket hang up错误的解决办法
Sep 25 NodeJs
轻松创建nodejs服务器(9):实现非阻塞操作
Dec 18 NodeJs
nodeJS删除文件方法示例
Dec 25 NodeJs
Ajax异步文件上传与NodeJS express服务端处理
Apr 01 NodeJs
nodejs个人博客开发第六步 数据分页
Apr 12 NodeJs
NodeJS、NPM安装配置步骤(windows版本) 以及环境变量详解
May 13 NodeJs
Express+Nodejs 下的登录拦截实现代码
Jul 01 NodeJs
NodeJS简单实现WebSocket功能示例
Feb 10 NodeJs
基于Koa(nodejs框架)对json文件进行增删改查的示例代码
Feb 02 NodeJs
详解nodejs http请求相关总结
Mar 31 NodeJs
监控Nodejs的性能实例代码
Jul 02 NodeJs
NodeJS制作爬虫全过程
Dec 22 #NodeJs
nodejs中操作mysql数据库示例
Dec 20 #NodeJs
轻松创建nodejs服务器(10):处理上传图片
Dec 18 #NodeJs
轻松创建nodejs服务器(10):处理POST请求
Dec 18 #NodeJs
轻松创建nodejs服务器(7):阻塞操作的实现
Dec 18 #NodeJs
轻松创建nodejs服务器(8):非阻塞是如何实现的
Dec 18 #NodeJs
轻松创建nodejs服务器(9):实现非阻塞操作
Dec 18 #NodeJs
You might like
综合图片计数器
2006/10/09 PHP
php下统计用户在线时间的一种尝试
2010/08/26 PHP
php利用iframe实现无刷新文件上传功能的代码
2011/09/29 PHP
php通过修改header强制图片下载的方法
2015/03/24 PHP
PHP PDOStatement::rowCount讲解
2019/02/01 PHP
JavaScript游戏之优化篇
2010/11/08 Javascript
script标签的 charset 属性使用说明
2010/12/04 Javascript
使用jquery实现div的tab切换实例代码
2013/05/27 Javascript
基于jQuery的图片不完全按比例自动缩小
2014/07/11 Javascript
js中实现多态采用和继承类似的方法
2014/08/22 Javascript
JS+CSS实现实用的单击输入框弹出选择框的方法
2015/02/28 Javascript
js实现新浪微博首页效果
2015/10/16 Javascript
JavaScrip调试技巧之断点调试
2015/10/22 Javascript
JS延时器提示框的应用实例代码解析
2016/04/27 Javascript
深入理解JavaScript中为什么string可以拥有方法
2016/05/24 Javascript
bootstrap multiselect 多选功能实现方法
2017/06/05 Javascript
vue监听input标签的value值方法
2018/08/27 Javascript
node链接mongodb数据库的方法详解【阿里云服务器环境ubuntu】
2019/03/07 Javascript
如何从零开始手写Koa2框架
2019/03/22 Javascript
详解如何搭建mpvue框架搭配vant组件库的小程序项目
2019/05/16 Javascript
Js实现复选框的全选、全不选反选功能代码实例
2020/02/28 Javascript
vue使用nprogress加载路由进度条的方法
2020/06/04 Javascript
Python中的map()函数和reduce()函数的用法
2015/04/27 Python
对python while循环和双重循环的实例详解
2019/08/23 Python
python监控nginx端口和进程状态
2019/09/06 Python
Python变量、数据类型、数据类型转换相关函数用法实例详解
2020/01/09 Python
浅谈keras通过model.fit_generator训练模型(节省内存)
2020/06/17 Python
华为菲律宾官方网站:HUAWEI Philippines
2021/02/23 全球购物
网站编辑求职信
2013/10/17 职场文书
庆七一活动方案
2014/01/25 职场文书
学习十八大报告感言
2014/02/04 职场文书
《落花生》教学反思
2014/02/25 职场文书
医院党员公开承诺书
2014/08/30 职场文书
作风大整顿心得体会
2014/09/10 职场文书
信贷客户经理岗位职责
2015/04/09 职场文书
JavaScript offset实现鼠标坐标获取和窗口内模块拖动
2021/05/30 Javascript