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 05 NodeJs
nodejs教程 安装express及配置app.js文件的详细步骤
May 11 NodeJs
nodejs文件操作模块FS(File System)常用函数简明总结
Jun 05 NodeJs
Nodejs异步回调的优雅处理方法
Sep 25 NodeJs
NodeJS学习笔记之Connect中间件应用实例
Jan 27 NodeJs
实例详解Nodejs 保存 payload 发送过来的文件
Jan 14 NodeJs
Nodejs进阶:如何将图片转成datauri嵌入到网页中去实例
Nov 21 NodeJs
图片上传之FileAPI与NodeJs
Jan 24 NodeJs
nodejs个人博客开发第五步 分配数据
Apr 12 NodeJs
nodejs mysql 实现分页的方法
Jun 06 NodeJs
nodejs 如何手动实现服务器
Aug 20 NodeJs
Nodejs实现的操作MongoDB数据库功能完整示例
Feb 02 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 正则 过滤html 的超链接
2009/06/02 PHP
探讨Hessian在PHP中的使用分析
2013/06/13 PHP
php实现通过stomp协议连接ActiveMQ操作示例
2020/02/23 PHP
javascript 写类方式之九
2009/07/05 Javascript
查询绑定数据岛的表格中的文本并修改显示方式的js代码
2009/12/15 Javascript
基于JavaScript实现鼠标悬浮弹出跟随鼠标移动的带箭头的信息层
2016/01/18 Javascript
搞定immutable.js详细说明
2016/05/02 Javascript
canvas学习之API整理笔记(二)
2016/12/29 Javascript
js实现模糊匹配功能
2017/02/15 Javascript
inner join 内联与left join 左联的实例代码
2017/09/18 Javascript
seajs实现强制刷新本地缓存的方法分析
2017/10/16 Javascript
nodejs实现简单的gulp打包
2017/12/21 NodeJs
angular 未登录状态拦截路由跳转的方法
2018/10/09 Javascript
JS动画实现回调地狱promise的实例代码详解
2018/11/08 Javascript
jQuery对底部导航进行跳转并高亮显示的实例代码
2019/04/23 jQuery
Python利用ElementTree模块处理XML的方法详解
2017/08/31 Python
Python语言描述最大连续子序列和
2017/12/05 Python
用Python写脚本,实现完全备份和增量备份的示例
2018/04/29 Python
Python使用sort和class实现的多级排序功能示例
2018/08/15 Python
Django的Modelforms用法简介
2019/07/27 Python
pytorch实现对输入超过三通道的数据进行训练
2020/01/15 Python
使用Django和Postgres进行全文搜索的实例代码
2020/02/13 Python
Tensorflow卷积实现原理+手写python代码实现卷积教程
2020/05/22 Python
Python ckeditor富文本编辑器代码实例解析
2020/06/22 Python
Python lambda表达式原理及用法解析
2020/08/18 Python
python爬虫爬取淘宝商品比价(附淘宝反爬虫机制解决小办法)
2020/12/03 Python
Python实现网络聊天室的示例代码(支持多人聊天与私聊)
2021/01/27 Python
美国在线购物频道:Shop LC
2019/04/21 全球购物
德国自然时尚和有机产品购物网站:Waschbär
2019/05/29 全球购物
高一新生军训方案
2014/05/12 职场文书
绘画专业自荐信
2014/07/04 职场文书
渠道运营商合作协议书范本
2014/10/06 职场文书
2014年社区矫正工作总结
2014/11/18 职场文书
2015年七一建党节活动方案
2015/05/05 职场文书
通过Qt连接OpenGauss数据库的详细教程
2021/06/23 PostgreSQL
vue实现在data里引入相对路径
2022/06/05 Vue.js