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之请求路由概述
Jul 05 NodeJs
nodejs教程之制作一个简单的文章发布系统
Nov 21 NodeJs
NodeJS制作爬虫全过程
Dec 22 NodeJs
iPhone手机上搭建nodejs服务器步骤方法
Jul 06 NodeJs
nodejs和php实现图片访问实时处理
Jan 05 NodeJs
nodejs入门教程四:URL相关模块用法分析
Apr 24 NodeJs
CentOS 安装NodeJS V8.0.0的方法
Jun 15 NodeJs
nodejs微信扫码支付功能实现
Feb 17 NodeJs
Linux Centos7.2下安装nodejs&amp;npm配置全局路径的教程
May 15 NodeJs
nodejs中实现修改用户路由功能
May 24 NodeJs
Nodejs实现图片上传、压缩预览、定时删除功能
Oct 25 NodeJs
Nodejs在局域网配置https访问的实现方法
Oct 17 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防止form重复提交的方法
2013/07/01 PHP
php使用curl发送json格式数据实例
2013/12/17 PHP
详谈PHP中的密码安全性Password Hashing
2017/02/04 PHP
用ASP将SQL搜索出来的内容导出为TXT的代码
2007/07/27 Javascript
使用JavaScript构建JSON格式字符串实现步骤
2013/03/22 Javascript
JS预览图像将本地图片显示到浏览器上
2013/08/25 Javascript
js 定时器setTimeout无法调用局部变量的解决办法
2013/11/28 Javascript
JSON无限折叠菜单编写实例
2013/12/16 Javascript
JS使用eval解析JSON的注意事项分析
2015/11/14 Javascript
Bootstrap每天必学之进度条
2015/11/30 Javascript
Vue中使用vee-validate表单验证的方法
2018/05/09 Javascript
VUE在for循环里面根据内容值动态的加入class值的方法
2018/08/12 Javascript
详解react内联样式使用webpack将px转rem
2018/09/13 Javascript
vue绑定事件后获取绑定事件中的this方法
2018/09/15 Javascript
Vue.js路由实现选项卡简单实例
2019/07/24 Javascript
浅谈vue权限管理实现及流程
2020/04/23 Javascript
js实现弹幕飞机效果
2020/08/27 Javascript
Python 常用的安装Module方式汇总
2017/05/06 Python
python中MethodType方法介绍与使用示例
2017/08/03 Python
Appium+python自动化之连接模拟器并启动淘宝APP(超详解)
2019/06/17 Python
解决Keras的自定义lambda层去reshape张量时model保存出错问题
2020/07/01 Python
Python3如何实现Win10桌面自动切换
2020/08/11 Python
Python使用内置函数setattr设置对象的属性值
2020/10/16 Python
如何使用css3实现一个类在线直播的队列动画的示例代码
2020/06/17 HTML / CSS
adidas瑞典官方网站:购买阿迪达斯鞋子和运动服
2019/12/11 全球购物
电子邮箱格式怎么写
2014/01/12 职场文书
宿舍使用违章电器检讨书
2014/01/12 职场文书
财务主管自我鉴定
2014/01/17 职场文书
房屋买卖协议书范本
2014/04/10 职场文书
学习雷锋寄语大全
2014/04/11 职场文书
2014年语文教研组工作总结
2014/12/06 职场文书
安全先进班组材料
2014/12/26 职场文书
幼儿园六一儿童节演讲稿
2015/03/19 职场文书
机修车间主任岗位职责
2015/04/08 职场文书
90后经典动画片排行:《数码宝贝》第二,《小鲤鱼历险记》在榜
2022/03/18 日漫
超越Nginx的Web服务器caddy优雅用法
2022/06/21 Servers