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 相关文章推荐
14款NodeJS Web框架推荐
Jul 11 NodeJs
轻松创建nodejs服务器(10):处理上传图片
Dec 18 NodeJs
在windows上用nodejs搭建静态文件服务器的简单方法
Aug 11 NodeJs
Nodejs中解决cluster模块的多进程如何共享数据问题
Nov 10 NodeJs
NodeJS仿WebApi路由示例
Feb 28 NodeJs
nodejs中全局变量的实例解析
Mar 07 NodeJs
解析NodeJS异步I/O的实现
Apr 13 NodeJs
nodejs 图片预览和上传的示例代码
Sep 30 NodeJs
Nodejs Express 通过log4js写日志到Logstash(ELK)
Aug 30 NodeJs
Nodejs实现多文件夹文件同步
Oct 17 NodeJs
nodejs遍历文件夹下并操作HTML/CSS/JS/PNG/JPG的方法
Nov 01 NodeJs
nodejs+express最简易的连接数据库的方法
Dec 23 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定界符
2014/06/19 PHP
Dwz与thinkphp整合下的数据导出到Excel实例
2014/12/04 PHP
PHP实现简易图形计算器
2020/08/28 PHP
JS对img进行操作(换图片/切图/轮换/停止)
2013/04/17 Javascript
js播放wav文件(源码)
2013/04/22 Javascript
json数据处理技巧(字段带空格、增加字段、排序等等)
2013/06/14 Javascript
javascript弹出层输入框(示例代码)
2013/12/11 Javascript
js文件包含的几种方式介绍
2014/09/28 Javascript
javascript使用call调用微信API
2014/12/15 Javascript
node.js中的fs.fchownSync方法使用说明
2014/12/16 Javascript
JS模式之简单的订阅者和发布者模式完整实例
2015/06/30 Javascript
jquery密码强度校验
2015/12/02 Javascript
jQuery调用WebMethod(PageMethod) NET2.0的方法
2016/04/15 Javascript
vue日期组件 支持vue1.0和2.0
2017/01/09 Javascript
package.json文件配置详解
2017/06/15 Javascript
详解angularJS自定义指令间的相互交互
2017/07/05 Javascript
nodejs实现一个word文档解析器思路详解
2018/08/14 NodeJs
TypeScript基础入门教程之三重斜线指令详解
2018/10/22 Javascript
vue使用Proxy实现双向绑定的方法示例
2019/03/20 Javascript
javascript实现抢购倒计时程序
2019/08/26 Javascript
JavaScript如何实现防止重复的网络请求的示例
2021/01/28 Javascript
写了个监控nginx进程的Python脚本
2012/05/10 Python
python中pass语句用法实例分析
2015/04/30 Python
Python中正则表达式的详细教程
2015/04/30 Python
基于python的图片修复程序(实现水印去除)
2018/06/04 Python
Python提取支付宝和微信支付二维码的示例代码
2019/02/15 Python
Django框架orM与自定义SQL语句混合事务控制操作
2019/06/27 Python
python标准库sys和OS的函数使用方法与实例详解
2020/02/12 Python
Python爬虫:Request Payload和Form Data的简单区别说明
2020/04/30 Python
cf搞笑广告词
2014/03/14 职场文书
工程索赔意向书
2014/08/30 职场文书
药店采购员岗位职责
2014/09/30 职场文书
计划生育证明格式及范本
2014/10/09 职场文书
2014年工程部工作总结
2014/11/25 职场文书
雷峰塔导游词
2015/02/09 职场文书
Go语言基础知识点介绍
2021/07/04 Golang