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实用示例 缩址还原
Dec 28 NodeJs
nodejs文件操作模块FS(File System)常用函数简明总结
Jun 05 NodeJs
nodejs实现黑名单中间件设计
Jun 17 NodeJs
在NodeJS中启用ECMAScript 6小结(windos以及Linux)
Jul 15 NodeJs
使用nodejs开发cli项目实例
Jun 03 NodeJs
NodeJS远程代码执行
Aug 28 NodeJs
使用nodejs下载风景壁纸
Feb 05 NodeJs
详解nodejs中exports和module.exports的区别
Feb 17 NodeJs
初识NodeJS服务端开发入门(Express+MySQL)
Apr 07 NodeJs
NodeJs安装npm包一直失败的解决方法
Apr 28 NodeJs
NodeJS自定义模块写法(详解)
Jun 27 NodeJs
nodejs 搭建简易服务器的图文教程(推荐)
Jul 18 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中使用PDF文档功能
2006/10/09 PHP
phpfans留言版用到的数据操作类和分页类
2007/01/04 PHP
mysql4.1以上版本连接时出现Client does not support authentication protocol问题解决办法
2007/03/15 PHP
关于更改Zend Studio/Eclipse代码风格主题的介绍
2013/06/23 PHP
php获取淘宝分类id示例
2014/01/16 PHP
php使用gzip压缩传输js和css文件的方法
2015/07/29 PHP
返回页面顶部top按钮通过锚点实现(自写)
2013/08/30 Javascript
jQuery 实现侧边浮动导航菜单效果
2014/12/26 Javascript
js实现用户注册协议倒计时的方法
2015/01/21 Javascript
jQuery实现折线图的方法
2015/02/28 Javascript
ECMAScript6函数默认参数
2015/06/12 Javascript
探讨JavaScript语句的执行过程
2016/01/28 Javascript
详解JavaScript数组和字符串中去除重复值的方法
2016/03/07 Javascript
js中遍历Map对象的简单实例
2016/08/08 Javascript
javaScript嗅探执行神器-sniffer.js
2017/02/14 Javascript
jquery中关于bind()方法的使用技巧分享
2017/03/30 jQuery
基于JavaScript实现的折半查找算法示例
2017/04/14 Javascript
js单线程的本质 Event Loop解析
2019/10/29 Javascript
Python实现针对给定单链表删除指定节点的方法
2018/04/12 Python
Python3远程监控程序的实现方法
2019/07/15 Python
Python 面向对象部分知识点小结
2020/03/09 Python
Django静态文件加载失败解决方案
2020/08/26 Python
python opencv实现简易画图板
2020/08/27 Python
StubHub中国:购买和出售全球活动门票
2020/01/01 全球购物
三星加拿大官方网上商店:Samsung CA
2020/12/18 全球购物
远东集团网络工程师面试题
2014/10/20 面试题
机械设计及其自动化求职推荐信
2014/02/17 职场文书
2014年幼儿园教学工作总结
2014/12/04 职场文书
委托书英文
2015/01/28 职场文书
本溪水洞导游词
2015/02/11 职场文书
安全生产学习心得体会
2016/01/18 职场文书
Oracle笔记
2021/04/05 Oracle
在前女友婚礼上,用Python破解了现场的WIFI还把名称改成了
2021/05/28 Python
python代码实现扫码关注公众号登录的实战
2021/11/01 Python
世界十大动漫制作公司排行榜,迪士尼上榜,第二是美国代表性文化符
2022/03/18 欧美动漫
Sql Server 行数据的某列值想作为字段列显示的方法
2022/04/20 SQL Server