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的url截取模块url-extract的使用实例
Nov 18 NodeJs
nodejs npm install全局安装和本地安装的区别
Jun 05 NodeJs
Nodejs极简入门教程(一):模块机制
Oct 25 NodeJs
nodejs实现遍历文件夹并统计文件大小
May 28 NodeJs
详解Nodejs基于mongoose模块的增删改查的操作
Dec 21 NodeJs
NodeJS遍历文件生产文件列表功能示例
Jan 22 NodeJs
nodejs中模块定义实例详解
Mar 18 NodeJs
nodejs使用express获取get和post传值及session验证的方法
Nov 09 NodeJs
nodejs实现简单的gulp打包
Dec 21 NodeJs
nodejs前端模板引擎swig入门详解
May 15 NodeJs
nodejs实现范围请求的实现代码
Oct 12 NodeJs
NodeJs操作MongoDB教程之分页功能以及常见问题
Apr 09 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
日本收入最高的漫画家:海贼王作者版税年收入高达8.45亿元
2020/03/04 日漫
smarty实例教程
2006/11/19 PHP
PHP中将数组转成XML格式的实现代码
2011/08/08 PHP
PHP缓存机制Output Control详解
2014/07/14 PHP
PHP实现UTF-8文件BOM自动检测与移除实例
2014/11/05 PHP
php使用ob_flush不能每隔一秒输出原理分析
2015/06/02 PHP
PHP面向对象程序设计组合模式与装饰模式详解
2016/12/02 PHP
纯文字版返回顶端的js代码
2013/08/01 Javascript
node.js中的fs.fstatSync方法使用说明
2014/12/15 Javascript
Bootstrap每天必学之级联下拉菜单
2016/03/27 Javascript
jQuery旋转插件jqueryrotate用法详解
2016/10/13 Javascript
JavaScript遍历Json串浏览器输出的结果不统一问题
2016/11/03 Javascript
JS常见疑难点分析之match,charAt,charCodeAt,map,search用法分析
2016/12/25 Javascript
微信小程序scroll-view横向滑动嵌套for循环的示例代码
2018/09/20 Javascript
详解如何用webpack4从零开始构建react开发环境
2019/01/27 Javascript
vue路由对不同界面进行传参及跳转的总结
2019/04/20 Javascript
jQuery轮播图功能制作方法详解
2019/12/03 jQuery
vue-router 2.0 跳转之router.push()用法说明
2020/08/12 Javascript
[36:52]DOTA2真视界:基辅特锦赛总决赛
2017/05/21 DOTA
用Python制作简单的朴素基数估计器的教程
2015/04/01 Python
在Python程序中进行文件读取和写入操作的教程
2015/04/28 Python
Python批量生成特定尺寸图片及图画任意文字的实例
2019/01/30 Python
python3 实现口罩抽签的功能
2020/03/11 Python
Python计算矩阵的和积的实例详解
2020/09/10 Python
Python实现PS滤镜中的USM锐化效果
2020/12/04 Python
推荐WEB开发者最佳HTML5和CSS3代码生成器
2015/11/24 HTML / CSS
Camper鞋西班牙官方网上商店:西班牙马略卡岛的鞋类品牌
2019/03/14 全球购物
屈臣氏官方旗舰店:亚洲享负盛名的保健及美妆零售商
2019/03/15 全球购物
求职信范文怎么写
2014/01/29 职场文书
市场推广策划方案
2014/06/02 职场文书
承诺书样本
2014/08/30 职场文书
暑假学习心得体会
2014/09/02 职场文书
授权收款委托书
2014/09/23 职场文书
爱心捐款感谢信
2015/01/20 职场文书
教师专业技术工作总结2015
2015/05/13 职场文书
MySQL Threads_running飙升与慢查询的相关问题解决
2021/05/08 MySQL