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进程管理模块forever详解
Jun 01 NodeJs
轻松创建nodejs服务器(9):实现非阻塞操作
Dec 18 NodeJs
NodeJS制作爬虫全过程
Dec 22 NodeJs
nodeJs内存泄漏问题详解
Sep 05 NodeJs
详解Nodejs的timers模块
Dec 22 NodeJs
详解nodejs微信公众号开发——6.自定义菜单
Apr 13 NodeJs
Nodejs中使用captchapng模块生成图片验证码
May 18 NodeJs
nodejs后台集成ueditor富文本编辑器的实例
Jul 11 NodeJs
Windows下使用Nodejs运行js的方法
Sep 02 NodeJs
NodeJS搭建HTTP服务器的实现步骤
Oct 12 NodeJs
详解nodejs解压版安装和配置(带有搭建前端项目脚手架)
Dec 06 NodeJs
nodejs中使用archive压缩文件的实现代码
Nov 26 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 时间转换Unix时间戳代码
2010/01/22 PHP
让PHP COOKIE立即生效,不用刷新就可以使用
2011/03/09 PHP
使用PHP函数scandir排除特定目录
2014/06/12 PHP
PHP判断用户是否已经登录(跳转到不同页面或者执行不同动作)
2016/09/22 PHP
使用PHP json_decode可能遇到的坑与解决方法
2017/08/03 PHP
php如何把表单内容提交到数据库
2019/07/08 PHP
php7 图形用户界面GUI 开发示例
2020/02/22 PHP
jquery的相对父元素和相对文档定位示例代码
2013/08/02 Javascript
查找Oracle高消耗语句的方法
2014/03/22 Javascript
json实现前后台的相互传值详解
2015/01/05 Javascript
javascript结合fileReader 实现上传图片
2015/01/30 Javascript
js实现简单的省市县三级联动效果实例
2016/02/18 Javascript
jQuery实现根据滚动条位置加载相应内容功能
2016/07/18 Javascript
js使用highlight.js高亮你的代码
2017/08/18 Javascript
JS获取本地地址及天气的方法实例小结
2019/05/10 Javascript
fastadmin中调用js的方法
2019/05/14 Javascript
Vue 实现点击空白处隐藏某节点的三种方式(指令、普通、遮罩)
2019/10/23 Javascript
微信小程序实现签字功能
2019/12/23 Javascript
js实现星星打分效果
2020/07/05 Javascript
[02:06]2018完美世界全国高校联赛秋季赛开始报名(附彩蛋)
2018/09/03 DOTA
[01:00:22]DOTA2-DPC中国联赛定级赛 LBZS vs Magma BO3第三场 1月10日
2021/03/11 DOTA
gearman的安装启动及python API使用实例
2014/07/08 Python
Python多线程编程(五):死锁的形成
2015/04/05 Python
Python实现SSH远程登陆,并执行命令的方法(分享)
2017/05/08 Python
python之Flask实现简单登录功能的示例代码
2018/12/24 Python
python 列表转为字典的两个小方法(小结)
2019/06/28 Python
详解window.open被浏览器拦截的解决方案
2019/07/18 HTML / CSS
美国在线鲜花速递:ProFlowers
2017/01/05 全球购物
缅怀革命先烈演讲稿
2014/05/14 职场文书
村党的群众路线教育实践活动总结材料
2014/10/31 职场文书
职工宿舍管理制度
2015/08/05 职场文书
新学期主题班会
2015/08/17 职场文书
班主任远程培训研修日志
2015/11/13 职场文书
虚拟机linux端mysql数据库无法远程访问的解决办法
2021/05/26 MySQL
分析Netty直接内存原理及应用
2021/06/14 Java/Android
vue3使用vuedraggable实现拖拽功能
2022/04/06 Vue.js