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的模块写法入门(实例代码)
Mar 07 NodeJs
Nodejs sublime text 3安装与配置
Jun 19 NodeJs
详解nodejs与javascript中的aes加密
May 22 NodeJs
NodeJs的优势和适合开发的程序
Aug 14 NodeJs
实例分析nodejs模块xml2js解析xml过程中遇到的坑
Mar 18 NodeJs
详解Nodejs之静态资源处理
Jun 05 NodeJs
Nodejs异步回调之异常处理实例分析
Jun 22 NodeJs
nodejs的路径问题的解决
Jun 30 NodeJs
NodeJS如何实现同步的方法示例
Aug 24 NodeJs
NodeJs之word文件生成与解析的实现代码
Apr 01 NodeJs
使用nodejs分离html文件里的js和css详解
Apr 12 NodeJs
nodejs检测因特网是否断开的解决方案
Apr 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基于yii框架实现生成ICO图标
2015/11/13 PHP
yii2-GridView在开发中常用的功能及技巧总结
2017/01/07 PHP
ECMAScript 基础知识
2007/06/29 Javascript
Javascript中的var_dump函数实现代码
2009/09/07 Javascript
jQuery实现单行文字间歇向上滚动源代码
2013/06/02 Javascript
JS常用正则表达式总结
2013/11/12 Javascript
ExtJS自定义主题(theme)样式详解
2013/11/18 Javascript
JS延迟加载加快页面打开速度示例代码
2013/12/30 Javascript
js中settimeout方法加参数的使用实例
2014/02/27 Javascript
纯js代码实现未知宽高的元素在指定元素中垂直水平居中显示
2015/09/12 Javascript
JavaScript实现自动生成网页元素功能(按钮、文本等)
2015/11/21 Javascript
js点击按钮实现带遮罩层的弹出视频效果
2015/12/19 Javascript
js添加事件的通用方法推荐
2016/05/15 Javascript
JavaScript实现定时页面跳转功能示例
2017/02/14 Javascript
AngularJS中scope的绑定策略实例分析
2017/10/30 Javascript
学习JS中的DOM节点以及操作
2018/04/30 Javascript
vue单页开发父子组件传值思路详解
2018/05/18 Javascript
详解webpack引入第三方库的方式以及注意事项
2019/01/15 Javascript
layui实现下拉复选功能的例子(包括数据的回显与上传)
2019/09/24 Javascript
Vue 通过公共字段,拼接两个对象数组的实例
2019/11/07 Javascript
Python 流程控制实例代码
2009/09/25 Python
python将文本分每两行一组并保存到文件
2018/03/19 Python
使用django-guardian实现django-admin的行级权限控制的方法
2018/10/30 Python
在Python中定义一个常量的方法
2018/11/10 Python
浅谈python中str字符串和unicode对象字符串的拼接问题
2018/12/04 Python
将string类型的数据类型转换为spark rdd时报错的解决方法
2019/02/18 Python
150行Python代码实现带界面的数独游戏
2020/04/04 Python
用CSS3的box-reflect设置文字倒影效果的方法讲解
2016/03/07 HTML / CSS
JAVA招聘远程笔试题
2015/07/23 面试题
党员干部承诺书
2014/03/25 职场文书
优秀大学生求职自荐信范文
2014/04/19 职场文书
技术比武方案
2014/05/19 职场文书
保证金退回承诺函格式
2015/01/21 职场文书
运动会开幕式致辞
2015/07/29 职场文书
python程序的组织结构详解
2021/12/06 Python
向Spring IOC 容器动态注册bean实现方式
2022/07/15 Java/Android