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 Express框架中处理404页面一个方式
May 28 NodeJs
nodejs npm install全局安装和本地安装的区别
Jun 05 NodeJs
nodejs中实现阻塞实例
Mar 24 NodeJs
nodejs实现获取当前url地址及url各种参数值
Jun 25 NodeJs
nodejs实现bigpipe异步加载页面方案
Jan 26 NodeJs
NodeJs——入门必看攻略
Jun 27 NodeJs
nodejs进阶(6)—连接MySQL数据库示例
Jan 07 NodeJs
nodejs个人博客开发第七步 后台登陆
Apr 12 NodeJs
NodeJs的fs读写删除移动监听
Apr 28 NodeJs
NodeJS收发GET和POST请求的示例代码
Aug 25 NodeJs
nodejs判断文件、文件夹是否存在及删除的方法
Nov 10 NodeJs
nodejs基础之常用工具模块util用法分析
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加MYSQL服务器
2006/10/09 PHP
PHP详细彻底学习Smarty
2008/03/27 PHP
php 获取可变函数参数的函数
2009/08/26 PHP
php获取url参数方法总结
2014/11/13 PHP
php使用str_replace实现输入框回车替换br的方法
2014/11/24 PHP
PHP中文乱码解决方案
2015/03/05 PHP
PHP程序员简单的开展服务治理架构操作详解(一)
2020/05/14 PHP
ArrayList类(增强版)
2007/04/04 Javascript
ajax上传时参数提交不更新等相关问题
2012/12/11 Javascript
jquery mobile实现拨打电话功能的几种方法
2013/08/05 Javascript
jQuery实现table隔行换色和鼠标经过变色的两种方法
2014/06/15 Javascript
js给网页加上背景音乐及选择音效的方法
2015/03/03 Javascript
JavaScript中的关联数组问题
2015/03/04 Javascript
chrome不支持form.submit的解决方案
2015/04/28 Javascript
jQuery操作基本控件方法实例分析
2015/12/31 Javascript
Nodejs如何复制文件
2016/03/09 NodeJs
xmlplus组件设计系列之分隔框(DividedBox)(8)
2017/05/02 Javascript
Node.js+jade抓取博客所有文章生成静态html文件的实例
2017/09/19 Javascript
详解Vue单元测试Karma+Mocha学习笔记
2018/01/31 Javascript
基于jQuery实现的设置文本区域的光标位置
2018/06/15 jQuery
JS中注入eval, Function等系统函数截获动态代码
2019/04/03 Javascript
angular多语言配置详解
2019/05/16 Javascript
JS实现放烟花效果
2020/03/10 Javascript
element-ui 实现响应式导航栏的示例代码
2020/05/08 Javascript
[34:08]2018DOTA2亚洲邀请赛3月29日 小组赛B组 VP VS EG
2018/03/30 DOTA
Python中__init__.py文件的作用详解
2016/09/18 Python
Python 爬虫学习笔记之多线程爬虫
2016/09/21 Python
Python实现打砖块小游戏代码实例
2019/05/18 Python
Python中使用aiohttp模拟服务器出现错误问题及解决方法
2020/10/31 Python
html5 自定义播放器核心代码
2013/12/20 HTML / CSS
html5在移动端的屏幕适应问题示例探讨
2014/06/15 HTML / CSS
美国家居装饰网上商店:Lulu & Georgia
2019/09/14 全球购物
秋季婚礼证婚词
2014/01/11 职场文书
个人总结与自我评价
2015/02/14 职场文书
Python Pandas解析读写 CSV 文件
2022/04/11 Python
笔记本自带的win11如何跳过联网激活?
2022/04/20 数码科技