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分页类代码分享
Jun 17 NodeJs
NodeJS学习笔记之Connect中间件模块(一)
Jan 27 NodeJs
nodejs连接mongodb数据库实现增删改查
Dec 01 NodeJs
详解Nodejs基于mongoose模块的增删改查的操作
Dec 21 NodeJs
nodejs使用express创建一个简单web应用
Mar 31 NodeJs
详解nodeJS之二进制buffer对象
Jun 03 NodeJs
nodejs后台集成ueditor富文本编辑器的实例
Jul 11 NodeJs
nodejs使用redis作为缓存介质实现的封装缓存类示例
Feb 07 NodeJs
nodejs异步编程基础之回调函数用法分析
Dec 26 NodeJs
nodeJS进程管理器pm2的使用
Jan 09 NodeJs
Sublime Text3 配置 NodeJs 环境的方法
May 20 NodeJs
Nodejs实现微信分账的示例代码
Jan 19 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
开发大型 PHP 项目的方法
2007/01/02 PHP
修改Zend引擎实现PHP源码加密的原理及实践
2008/04/14 PHP
php 操作调试的方法
2012/07/12 PHP
PHP中提问频率最高的11个面试题和答案
2014/09/02 PHP
微信支付开发动态链接Native支付
2016/07/12 PHP
ThinkPHP5框架实现简单的批量查询功能示例
2018/06/07 PHP
Jquery iframe内部出滚动条
2010/02/11 Javascript
JS request函数 用来获取url参数
2010/05/17 Javascript
js中scrollHeight,scrollWidth,scrollLeft,scrolltop等差别介绍
2012/05/16 Javascript
JS getAttribute和setAttribute(取得和设置属性)的使用介绍
2013/07/10 Javascript
当前页禁止复制粘贴截屏代码小集
2013/07/24 Javascript
一款基jquery超炫的动画导航菜单可响应单击事件
2014/11/02 Javascript
jQuery统计指定子元素数量的方法
2015/03/17 Javascript
JQuery记住用户名密码实现下次自动登录功能
2015/04/27 Javascript
javascript自动恢复文本框点击清除后的默认文本
2016/01/12 Javascript
bootstrap读书笔记之CSS组件(上)
2016/10/17 Javascript
原生js实现图片放大缩小计时器效果
2017/01/20 Javascript
JS实现简易刻度时钟示例代码
2017/03/11 Javascript
使用cookie绕过验证码登录的实现代码
2017/10/12 Javascript
vue路由拦截及页面跳转的设置方法
2018/05/24 Javascript
原生JS实现简单的无缝自动轮播效果
2018/09/26 Javascript
node中实现删除目录的几种方法
2019/06/24 Javascript
vue-video-player实现实时视频播放方式(监控设备-rtmp流)
2020/08/10 Javascript
JS实现放大镜效果
2020/09/21 Javascript
Python爬虫包BeautifulSoup实例(三)
2018/06/17 Python
对TensorFlow的assign赋值用法详解
2018/07/30 Python
在Python中定义一个常量的方法
2018/11/10 Python
详解Python 爬取13个旅游城市,告诉你五一大家最爱去哪玩?
2019/05/07 Python
对Python3之方法的覆盖与super函数详解
2019/06/26 Python
jupyter notebook清除输出方式
2020/04/10 Python
Django权限设置及验证方式
2020/05/13 Python
法学院方阵解说词
2014/01/29 职场文书
学生期末评语大全
2014/04/30 职场文书
学习教师法的心得体会
2014/09/03 职场文书
解决Navicat for Mysql连接报错1251的问题(连接失败)
2021/05/27 MySQL
JS实现刷新网页后之前浏览位置保持不变示例详解
2022/08/14 Javascript