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 相关文章推荐
基于NodeJS的前后端分离的思考与实践(四)安全问题解决方案
Sep 26 NodeJs
Nodejs中读取中文文件编码问题、发送邮件和定时任务实例
Jan 01 NodeJs
基于html5和nodejs相结合实现websocket即使通讯
Nov 19 NodeJs
nodejs微信公众号支付开发
Sep 19 NodeJs
nodejs实现发出蜂鸣声音(系统报警声)的方法
Jan 18 NodeJs
详解nodejs微信公众号开发——4.自动回复各种消息
Apr 11 NodeJs
NodeJS创建最简单的HTTP服务器
May 15 NodeJs
使用nodeJs来安装less及编译less文件为css文件的方法
Nov 20 NodeJs
nodejs结合socket.io实现websocket通信功能的方法
Jan 12 NodeJs
详解nodejs 配置文件处理方案
Jan 02 NodeJs
Nodejs监听日志文件的变化的过程解析
Aug 04 NodeJs
一文秒懂nodejs中的异步编程
Jan 28 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
十天学会php之第八天
2006/10/09 PHP
smarty模板嵌套之include与fetch性能测试
2010/12/05 PHP
php筛选不存在的图片资源
2015/04/28 PHP
CentOS系统中PHP安装扩展的方式汇总
2017/04/09 PHP
PHP后台备份MySQL数据库的源码实例
2019/03/18 PHP
jQuery JSON实现无刷新三级联动实例探讨
2013/05/28 Javascript
基于JQuery的列表拖动排序实现代码
2013/10/01 Javascript
js单例模式的两种方案
2013/10/22 Javascript
21个JavaScript事件(Events)属性汇总
2014/12/02 Javascript
js进行表单验证实例分析
2015/02/10 Javascript
jQuery实现图片加载完成后改变图片大小的方法
2016/03/29 Javascript
有关jQuery中parent()和siblings()的小问题
2016/06/01 Javascript
JavaScript中的this引用(推荐)
2016/08/05 Javascript
JavaScript数组去重由慢到快由繁到简(优化篇)
2016/08/26 Javascript
jQuery Easy UI中根据第一个下拉框选中的值设置第二个下拉框是否可以编辑
2016/11/29 Javascript
基于vue实现移动端圆形旋钮插件效果
2018/11/28 Javascript
vue.js实现简单购物车功能
2020/05/30 Javascript
JavaScript仿京东轮播图效果
2021/02/25 Javascript
[01:24:16]2018DOTA2亚洲邀请赛 4.6 全明星赛
2018/04/10 DOTA
python list中append()与extend()用法分享
2013/03/24 Python
Python基于scrapy采集数据时使用代理服务器的方法
2015/04/16 Python
Windows和Linux下Python输出彩色文字的方法教程
2017/05/02 Python
TensorFlow saver指定变量的存取
2018/03/10 Python
python3+PyQt5实现自定义流体混合窗口部件
2018/04/24 Python
Python 生成 -1~1 之间的随机数矩阵方法
2018/08/04 Python
对Python函数设计规范详解
2019/07/19 Python
python3在同一行内输入n个数并用列表保存的例子
2019/07/20 Python
python list转置和前后反转的例子
2019/08/26 Python
python爬虫 线程池创建并获取文件代码实例
2019/09/28 Python
SKECHERS官方旗舰店:美国舒适运动休闲品牌
2017/12/22 全球购物
电大学习个人自我评价范文
2013/10/04 职场文书
庆元旦广播稿
2014/02/10 职场文书
致跳远运动员加油稿
2014/02/11 职场文书
使用feign服务调用添加Header参数
2021/06/23 Java/Android
Python捕获、播放和保存摄像头视频并提高视频清晰度和对比度
2022/04/14 Python
MySQL表字段数量限制及行大小限制详情
2022/07/23 MySQL