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 相关文章推荐
使用DNode实现php和nodejs之间通信的简单实例
Jul 06 NodeJs
Nodejs实战心得之eventproxy模块控制并发
Oct 27 NodeJs
Nodejs的express使用教程
Nov 23 NodeJs
Nodejs中的this详解
Mar 26 NodeJs
NodeJs读取JSON文件格式化时的注意事项
Sep 25 NodeJs
用nodejs搭建websocket服务器
Jan 23 NodeJs
初识NodeJS服务端开发入门(Express+MySQL)
Apr 07 NodeJs
Nodejs--post的公式详解
Apr 29 NodeJs
nodejs实现的简单web服务器功能示例
Mar 15 NodeJs
NodeJS使用Range请求实现下载功能的方法示例
Oct 12 NodeJs
使用nodejs分离html文件里的js和css详解
Apr 12 NodeJs
nodeJs项目在阿里云的简单部署
Nov 27 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生成sitemap.xml地图函数
2013/11/13 PHP
php页面防重复提交方法总结
2013/11/25 PHP
php实现文件与16进制相互转换的方法示例
2017/02/16 PHP
PHP实现简单计算器小程序
2020/08/28 PHP
PHP xpath()函数讲解
2019/02/11 PHP
跟着JQuery API学Jquery 之三 筛选
2010/04/09 Javascript
基于jquery的图片的切换(以数字的形式)
2011/02/14 Javascript
javascript 原型继承介绍
2011/08/30 Javascript
JavaScript制作简易的微信打飞机
2015/03/31 Javascript
js插件YprogressBar实现漂亮的进度条效果
2015/04/20 Javascript
最简单的JavaScript图片轮播代码(两种方法)
2015/12/18 Javascript
JavaScript正则表达式小结(test|match|search|replace|split|exec)
2016/12/08 Javascript
AngularJS 中ui-view传参的实例详解
2017/08/25 Javascript
vue组件父与子通信详解(一)
2017/11/07 Javascript
layui radio性别单选框赋值方法
2018/08/15 Javascript
vue中使用element ui的弹窗与echarts之间的问题详解
2019/10/25 Javascript
python函数形参用法实例分析
2015/08/04 Python
selenium+python自动化测试之环境搭建
2019/01/23 Python
python使用matplotlib画柱状图、散点图
2019/03/18 Python
python集合是否可变总结
2019/06/20 Python
Python遍历字典方式就实例详解
2019/12/28 Python
django列表筛选功能的实现代码
2020/03/27 Python
Django CBV模型源码运行流程详解
2020/08/17 Python
python如何构建mock接口服务
2021/01/28 Python
HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题
2021/01/19 HTML / CSS
电大毕业生自我鉴定
2013/11/10 职场文书
人力资源经理自我评价
2014/01/04 职场文书
广告创意求职信
2014/03/17 职场文书
个人担保书格式范文
2014/05/12 职场文书
药剂专业求职信
2014/06/20 职场文书
不尊敬老师检讨书范文
2014/11/19 职场文书
2014年幼儿园班级工作总结
2014/12/17 职场文书
教师调动申请报告
2015/05/18 职场文书
Python 解决空列表.append() 输出为None的问题
2021/05/23 Python
Mysql8.0递归查询的简单用法示例
2021/08/04 MySQL
解析python中的jsonpath 提取器
2022/01/18 Python