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基本语法和类型
Feb 13 NodeJs
nodejs URL模块操作URL相关方法介绍
Mar 03 NodeJs
使用nodejs开发cli项目实例
Jun 03 NodeJs
nodejs模块nodemailer基本使用-邮件发送示例(支持附件)
Mar 28 NodeJs
nodejs multer实现文件上传与下载
May 10 NodeJs
让nodeJS支持ES6的词法----babel的安装和使用方法
Jul 31 NodeJs
用nodejs实现json和jsonp服务的方法
Aug 25 NodeJs
详解redis在nodejs中的应用
May 02 NodeJs
Mac下通过brew安装指定版本的nodejs教程
May 17 NodeJs
Nodejs把接收图片base64格式保存为文件存储到服务器上
Sep 26 NodeJs
NodeJs操作MongoDB教程之分页功能以及常见问题
Apr 09 NodeJs
windows如何把已安装的nodejs高版本降级为低版本(图文教程)
Dec 14 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图片处理:加水印、缩略图的实现(自定义函数:watermark、thumbnail)
2010/12/02 PHP
php中将数组存到文件里的实现代码
2012/01/19 PHP
php获取YouTube视频信息的方法
2015/02/11 PHP
php 文件下载 出现下载文件内容乱码损坏的解决方法(推荐)
2016/11/16 PHP
张孝祥JavaScript学习阶段性总结(2)--(X)HTML学习
2007/02/03 Javascript
javascript 构建一个xmlhttp对象池合理创建和使用xmlhttp对象
2010/01/15 Javascript
Javascript this 的一些学习总结
2012/08/31 Javascript
JavaScript中的闭包(Closure)详细介绍
2014/12/30 Javascript
Javascript实现颜色rgb与16进制转换的方法
2015/04/18 Javascript
js获取滚动距离的方法
2015/05/30 Javascript
基于BootStrap的图片轮播效果展示实例代码
2016/05/23 Javascript
js窗口震动小程序分享
2016/11/28 Javascript
微信小程序 网络请求(post请求,get请求)
2017/01/17 Javascript
Bootstrap下拉菜单更改为悬停(hover)触发的方法
2017/05/24 Javascript
jQuery简单绑定单个事件的方法示例
2017/06/10 jQuery
在vue项目中使用sass的配置方法
2018/03/20 Javascript
angular4 共享服务在多个组件中数据通信的示例
2018/03/30 Javascript
微信小程序之swiper轮播图中的图片自适应高度的方法
2018/04/23 Javascript
angular6的响应式表单的实现
2018/10/10 Javascript
使用jQuery实现购物车
2020/10/29 jQuery
30分钟搭建Python的Flask框架并在上面编写第一个应用
2015/03/30 Python
Python3.x版本中新的字符串格式化方法
2015/04/24 Python
Django中URL视图函数的一些高级概念介绍
2015/07/20 Python
mysql 之通过配置文件链接数据库
2017/08/12 Python
Python3网络爬虫之使用User Agent和代理IP隐藏身份
2017/11/23 Python
Python tkinter常用操作代码实例
2020/01/03 Python
Python爬虫工具requests-html使用解析
2020/04/29 Python
python使用numpy中的size()函数实例用法详解
2021/01/29 Python
梅西百货澳大利亚:Macy’s Australia
2017/07/26 全球购物
Joie官方网上商店:购买服装和女装配饰
2018/06/05 全球购物
c/c++某大公司的两道笔试题
2014/02/02 面试题
如何清空Session
2015/02/23 面试题
红领巾广播站广播稿
2014/02/01 职场文书
高中家长意见怎么写
2015/06/03 职场文书
使用Python的开发框架Brownie部署以太坊智能合约
2021/05/28 Python
nginx共享内存的机制详解
2022/03/21 Servers