NodeJS制作爬虫全过程


Posted in NodeJs onDecember 22, 2014

今天来学习alsotang的爬虫教程,跟着把CNode简单地爬一遍。

建立项目craelr-demo
我们首先建立一个Express项目,然后将app.js的文件内容全部删除,因为我们暂时不需要在Web端展示内容。当然我们也可以在空文件夹下直接 npm install express来使用我们需要的Express功能。

目标网站分析
如图,这是CNode首页一部分div标签,我们就是通过这一系列的id、class来定位我们需要的信息。
NodeJS制作爬虫全过程

使用superagent获取源数据

superagent就是ajax API来使用的Http库,它的使用方法与jQuery差不多,我们通过它发起get请求,在回调函数中输出结果。

var express = require('express');

var url = require('url'); //解析操作url

var superagent = require('superagent'); //这三个外部依赖不要忘记npm install

var cheerio = require('cheerio');

var eventproxy = require('eventproxy');

var targetUrl = 'https://cnodejs.org/';

superagent.get(targetUrl)

    .end(function (err, res) {

        console.log(res);

    });

它的res结果为一个包含目标url信息的对象,网站内容主要在其text(string)里。
NodeJS制作爬虫全过程

使用cheerio解析

cheerio充当服务器端的jQuery功能,我们先使用它的.load()来载入HTML,再通过CSS selector来筛选元素。

var $ = cheerio.load(res.text);

//通过CSS selector来筛选数据

$('#topic_list .topic_title').each(function (idx, element) {

    console.log(element);

});

其结果为一个个对象,调用 .each(function(index, element))函数来遍历每一个对象,返回的是HTML DOM Elements。
NodeJS制作爬虫全过程

输出 console.log($element.attr('title'));的结果为 广州 2014年12月06日 NodeParty 之 UC 场
之类的标题,输出 console.log($element.attr('href'));的结果为 /topic/545c395becbcb78265856eb2之类的url。再用NodeJS1的url.resolve()函数来补全完整的url。

superagent.get(tUrl)

    .end(function (err, res) {

        if (err) {

            return console.error(err);

        }

        var topicUrls = [];

        var $ = cheerio.load(res.text);

        // 获取首页所有的链接

        $('#topic_list .topic_title').each(function (idx, element) {

            var $element = $(element);

            var href = url.resolve(tUrl, $element.attr('href'));

            console.log(href);

            //topicUrls.push(href);

        });

    });

使用eventproxy来并发抓取每个主题的内容
教程上展示了深度嵌套(串行)方法和计数器方法的例子,eventproxy就是使用事件(并行)方法来解决这个问题。当所有的抓取完成后,eventproxy接收到事件消息自动帮你调用处理函数。

//第一步:得到一个 eventproxy 的实例

var ep = new eventproxy();

//第二步:定义监听事件的回调函数。

//after方法为重复监听

//params: eventname(String) 事件名,times(Number) 监听次数, callback 回调函数

ep.after('topic_html', topicUrls.length, function(topics){

    // topics 是个数组,包含了 40 次 ep.emit('topic_html', pair) 中的那 40 个 pair

    //.map

    topics = topics.map(function(topicPair){

        //use cheerio

        var topicUrl = topicPair[0];

        var topicHtml = topicPair[1];

        var $ = cheerio.load(topicHtml);

        return ({

            title: $('.topic_full_title').text().trim(),

            href: topicUrl,

            comment1: $('.reply_content').eq(0).text().trim()

        });

    });

    //outcome

    console.log('outcome:');

    console.log(topics);

});

//第三步:确定放出事件消息的

topicUrls.forEach(function (topicUrl) {

    superagent.get(topicUrl)

        .end(function (err, res) {

            console.log('fetch ' + topicUrl + ' successful');

            ep.emit('topic_html', [topicUrl, res.text]);

        });

});

结果如下

NodeJS制作爬虫全过程

扩展练习(挑战)

获取留言用户名和积分

NodeJS制作爬虫全过程

在文章页面的源码找到评论的用户class名,classname为reply_author。console.log第一个元素 $('.reply_author').get(0)可以看到,我们需要获取东西都在这里头。
NodeJS制作爬虫全过程

首先,我们先对一篇文章进行抓取,一次性把需要的都得到即可。

var userHref = url.resolve(tUrl, $('.reply_author').get(0).attribs.href);

console.log(userHref);

console.log($('.reply_author').get(0).children[0].data);

我们可以通过https://cnodejs.org/user/username抓取积分信息

$('.reply_author').each(function (idx, element) {

var $element = $(element);

console.log($element.attr('href'));

});

在用户信息页面 $('.big').text().trim()即为积分信息。

使用cheerio的函数.get(0)为获取第一个元素。

var userHref = url.resolve(tUrl, $('.reply_author').get(0).attribs.href);

console.log(userHref);

这只是对于单个文章的抓取,对于40个还有需要修改的地方。

NodeJs 相关文章推荐
Nodejs极简入门教程(二):定时器
Oct 25 NodeJs
NodeJS学习笔记之Connect中间件应用实例
Jan 27 NodeJs
nodejs实现bigpipe异步加载页面方案
Jan 26 NodeJs
详解nodejs与javascript中的aes加密
May 22 NodeJs
Nodejs基于LRU算法实现的缓存处理操作示例
Mar 17 NodeJs
详解nodejs中的process进程
Mar 19 NodeJs
详解Nodejs 通过 fs.createWriteStream 保存文件
Oct 10 NodeJs
Nodejs实现多文件夹文件同步
Oct 17 NodeJs
nodejs异步编程基础之回调函数用法分析
Dec 26 NodeJs
如何让Nodejs支持H5 History模式(connect-history-api-fallback源码分析)
May 30 NodeJs
Nodejs封装类似express框架的路由实例详解
Jan 05 NodeJs
使用nodejs实现JSON文件自动转Excel的工具(推荐)
Jun 24 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
轻松创建nodejs服务器(6):作出响应
Dec 18 #NodeJs
You might like
删除及到期域名的查看(抢域名必备哦)
2008/05/14 PHP
PHP 反向排序和随机排序代码
2010/06/30 PHP
深入php socket的讲解与实例分析
2013/06/13 PHP
php版本的cron定时任务执行器使用实例
2014/08/19 PHP
ThinkPHP中使用Ueditor富文本编辑器
2015/09/02 PHP
基于ThinkPHP+uploadify+upload+PHPExcel 无刷新导入数据
2015/09/23 PHP
mysqli扩展无法在PHP7下升级问题的解决
2019/09/10 PHP
jQuery中remove()方法用法实例
2014/12/25 Javascript
解决jquery插件:TypeError:$.browser is undefined报错的方法
2015/11/21 Javascript
微信小程序 跳转传参数与传对象详解及实例代码
2017/03/14 Javascript
详解Vue项目编译后部署在非网站根目录的解决方案
2018/04/26 Javascript
React 路由懒加载的几种实现方案
2018/10/23 Javascript
基于vue的验证码组件的示例代码
2019/01/22 Javascript
[53:18]Spirit vs Liquid Supermajor小组赛A组 BO3 第三场 6.2
2018/06/03 DOTA
Python中datetime模块参考手册
2017/01/13 Python
django+js+ajax实现刷新页面的方法
2017/05/22 Python
python判断一个集合是否为另一个集合的子集方法
2018/05/04 Python
PyTorch学习笔记之回归实战
2018/05/28 Python
spark: RDD与DataFrame之间的相互转换方法
2018/06/07 Python
python实现音乐下载的统计
2018/06/20 Python
Flask之请求钩子的实现
2018/12/23 Python
Python批量修改图片分辨率的实例代码
2019/07/04 Python
python实现的汉诺塔算法示例
2019/10/23 Python
Python 模拟动态产生字母验证码图片功能
2019/12/24 Python
Python自动登录QQ的实现示例
2020/08/28 Python
详解基于Facecognition+Opencv快速搭建人脸识别及跟踪应用
2021/01/21 Python
关于HTML5+ API plusready的兼容问题
2020/11/20 HTML / CSS
欧缇丽加拿大官方网站:Caudalie加拿大
2019/07/18 全球购物
豪华床上用品 :Jennifer Adams
2019/09/15 全球购物
俄罗斯设计师家具购物网站:The Furnish
2019/12/01 全球购物
工作岗位说明书模板
2014/05/09 职场文书
大学生党员自我批评思想汇报
2014/10/10 职场文书
纪检部部长竞选稿
2015/11/21 职场文书
党员心得体会范文2016
2016/01/23 职场文书
中学语文教学反思
2016/02/16 职场文书
Python初识逻辑与if语句及用法大全
2021/08/07 Python