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(二)--- Node.js事件模块
May 21 NodeJs
nodejs中实现阻塞实例
Mar 24 NodeJs
Nodejs从有门道无门菜鸟起飞必看教程
Jul 20 NodeJs
简单实现nodejs上传功能
Jan 14 NodeJs
Express+Nodejs 下的登录拦截实现代码
Jul 01 NodeJs
nodejs 搭建简易服务器的图文教程(推荐)
Jul 18 NodeJs
Nodejs进阶之服务端字符编解码和乱码处理
Sep 04 NodeJs
nodejs+mongodb+vue前后台配置ueditor的示例代码
Jan 02 NodeJs
NodeJS 实现多语言的示例代码
Sep 11 NodeJs
NodeJS加密解密及node-rsa加密解密用法详解
Oct 12 NodeJs
CentOS7中源码编译安装NodeJS的完整步骤
Oct 13 NodeJs
NodeJS 文件夹拷贝以及删除功能
Sep 03 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
解析mysql中UNIX_TIMESTAMP()函数与php中time()函数的区别
2013/06/24 PHP
Zend Framework实现多文件上传功能实例
2016/03/21 PHP
php实现用户登陆简单实例
2017/04/04 PHP
js压缩利器
2007/02/20 Javascript
JavaScript 仿关机效果的图片层
2008/12/26 Javascript
禁止你的左键复制实用技巧
2013/01/04 Javascript
js中Math之random,round,ceil,floor的用法总结
2013/12/26 Javascript
iframe实用操作锦集
2014/04/22 Javascript
深入浅出分析javaScript中this用法
2015/05/09 Javascript
使用Meteor配合Node.js编写实时聊天应用的范例
2015/06/23 Javascript
配置Grunt的Task时通配符支持和动态生成文件名问题
2015/09/06 Javascript
JavaScript基础知识及常用方法总结
2016/01/10 Javascript
BootStrap扔进Django里的方法详解
2016/05/13 Javascript
JS获取一个未知DIV高度的方法
2016/08/09 Javascript
JS实现DIV高度自适应窗口示例
2017/02/16 Javascript
微信小程序开发的基本流程步骤
2019/01/31 Javascript
解决Layui中templet中a的onclick参数传递的问题
2019/09/20 Javascript
基于better-scroll 实现歌词联动功能的代码
2020/05/07 Javascript
vue添加自定义右键菜单的完整实例
2020/12/08 Vue.js
Python简单实现两个任意字符串乘积的方法示例
2018/04/12 Python
解决seaborn在pycharm中绘图不出图的问题
2018/05/24 Python
Python面向对象程序设计OOP入门教程【类,实例,继承,重载等】
2019/01/05 Python
Python3实现的简单三级菜单功能示例
2019/03/12 Python
如何用Python来搭建一个简单的推荐系统
2019/08/07 Python
django认证系统实现自定义权限管理的方法
2019/08/28 Python
深入浅析Python科学计算库Scipy及安装步骤
2019/10/12 Python
利用Python脚本实现自动刷网课
2020/02/03 Python
Pygame的程序开始示例代码
2020/05/07 Python
python3用PyPDF2解析pdf文件,用正则匹配数据方式
2020/05/12 Python
python的数学算法函数及公式用法
2020/11/18 Python
手机业务员岗位职责
2013/12/13 职场文书
幼儿园优秀班主任事迹材料
2014/05/14 职场文书
小学先进集体事迹材料
2014/05/31 职场文书
学雷锋团日活动总结
2015/05/06 职场文书
幼儿园庆元旦主持词
2015/07/06 职场文书
Python 数据可视化之Bokeh详解
2021/11/02 Python