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访问ActiveX对象,以操作Access数据库为例。
Dec 15 NodeJs
Nodejs爬虫进阶教程之异步并发控制
Feb 15 NodeJs
nodejs使用express创建一个简单web应用
Mar 31 NodeJs
使用 NodeJS+Express 开发服务端的简单介绍
Apr 07 NodeJs
Nodejs读取文件时相对路径的正确写法(使用fs模块)
Apr 27 NodeJs
Nodejs--post的公式详解
Apr 29 NodeJs
详解nodejs异步I/O和事件循环
Jun 07 NodeJs
深入浅析Nodejs的Http模块
Jun 20 NodeJs
NodeJS收发GET和POST请求的示例代码
Aug 25 NodeJs
nodejs对express中next函数的一些理解
Sep 08 NodeJs
nodejs实现OAuth2.0授权服务认证
Dec 27 NodeJs
nodejs异步编程基础之回调函数用法分析
Dec 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+ajax实时刷新简单实例
2015/02/25 PHP
使用PHP如何实现高效安全的ftp服务器(一)
2015/12/20 PHP
PHP中addslashes()和stripslashes()实现字符串转义和还原用法实例
2016/01/07 PHP
PHP反射API示例分享
2016/10/08 PHP
JS随机生成不重复数据的实例方法
2013/07/17 Javascript
js获取URL的参数的方法(getQueryString)示例
2013/09/29 Javascript
JavaScript学习笔记之JS对象
2015/01/22 Javascript
jquery实现简单手风琴菜单效果实例
2015/06/13 Javascript
基于JS实现省市联动效果代码分享
2016/06/06 Javascript
jQuery实现的超链接提示效果示例【附demo源码下载】
2016/09/09 Javascript
JavaScript Ajax实现异步通信
2016/12/14 Javascript
详解AngularJs路由之Ui-router-resolve(预加载)
2017/06/13 Javascript
详解React中的组件通信问题
2017/07/31 Javascript
JavaScript多态与封装实例分析
2018/07/27 Javascript
详解Vue+axios+Node+express实现文件上传(用户头像上传)
2018/08/10 Javascript
微信小程序使用npm支持踩坑
2018/11/07 Javascript
微信小程序全选多选效果实现代码解析
2020/01/21 Javascript
JS实现横向跑马灯效果代码
2020/04/20 Javascript
Js利用正则表达式去除字符串的中括号
2020/11/23 Javascript
Python的Flask框架中Flask-Admin库的简单入门指引
2015/04/07 Python
Python3中的2to3转换工具使用示例
2015/06/12 Python
深入理解python中的闭包和装饰器
2016/06/12 Python
Python-jenkins模块之folder相关操作介绍
2020/05/12 Python
keras 使用Lambda 快速新建层 添加多个参数操作
2020/06/10 Python
使用pytorch实现论文中的unet网络
2020/06/24 Python
python如何实时获取tcpdump输出
2020/09/16 Python
HTML5学习笔记之History API
2015/02/26 HTML / CSS
美国儿童玩具、装扮和玩偶商店:Magic Cabin
2018/09/02 全球购物
工程总经理工作职责
2013/12/09 职场文书
《社戏》教学反思
2014/04/15 职场文书
煤矿安全生产月活动总结
2014/07/05 职场文书
加薪通知
2015/04/25 职场文书
呼兰河传读书笔记
2015/06/30 职场文书
校长新学期寄语2016
2015/12/04 职场文书
2016医师资格考试考生诚信考试承诺书
2016/03/25 职场文书
基于Redis位图实现用户签到功能
2021/05/08 Redis