Node.js异步特性初体验(采集器雏形)
Node.js 总是吹牛逼说自己异步特性多么多么厉害,但是对于初学者来说,要找一个能好好利用异步的场景不容易。我想来想去,爬虫的场景就比较适合,没事就异步并发地爬几个网站玩玩。
我们这回需要用到三个依赖,分别是 express,superagent 和 cheerio。
先介绍一下,
superagent(http://visionmedia.github.io/superagent/ ) 是个 http 方面的库,可以发起 get 或 post 请求。
cheerio(https://github.com/cheeriojs/cheerio ) 大家可以理解成一个 Node.js 版的 jquery,用来从网页中以 css selector 取数据,使用方式跟 jquery 一样一样的。
还记得我们怎么新建一个项目吗?
- 新建一个文件夹,进去之后
npm init
- 安装依赖
npm install --save PACKAGE_NAME
- 写应用逻辑
我们应用的核心逻辑长这样
app.get('/', function (req, res, next) { // 用 superagent 去抓取 http://www.daliane.com/ 的内容 superagent.get('http://www.daliane.com/') .end(function (err, sres) { // 常规的错误处理 if (err) { return next(err); } // sres.text 里面存储着网页的 html 内容,将它传给 cheerio.load 之后 // 就可以得到一个实现了 jquery 接口的变量,我们习惯性地将它命名为 `$` // 剩下就都是 jquery 的内容了 var $ = cheerio.load(sres.text); var items = []; $('section.content h1.entry-title a').each(function (idx, element) { var $element = $(element); items.push({ title: $element.attr('title'), href: $element.attr('href') }); }); res.send(items); }); });
OK,一个简单的爬虫就是这么简单。这里我们还没有利用到 Node.js 的异步并发特性。不过下两章内容都是关于异步控制的。
具体的实施。
[irteam@CGDLUIT7501 lesson2]$ npm install –save superagent
npm WARN package.json studynodejs@1.0.0 No repository field.
npm WARN package.json studynodejs@1.0.0 No README data
superagent@0.21.0 node_modules/superagent
├── extend@1.2.1
├── methods@1.0.1
├── cookiejar@2.0.1
├── component-emitter@1.1.2
├── reduce-component@1.0.1
├── qs@1.2.0
├── mime@1.2.11
├── formidable@1.0.14
├── readable-stream@1.0.27-1 (isarray@0.0.1, inherits@2.0.1, string_decoder@0.10 .31, core-util-is@1.0.1)
├── debug@2.1.1 (ms@0.6.2)
└── form-data@0.1.3 (async@0.9.0, combined-stream@0.0.7)
[irteam@CGDLUIT7501 lesson2]$ npm install –save cheerio
npm WARN package.json studynodejs@1.0.0 No repository field.
npm WARN package.json studynodejs@1.0.0 No README data
cheerio@0.18.0 node_modules/cheerio
├── entities@1.1.1
├── lodash@2.4.1
├── dom-serializer@0.0.1 (domelementtype@1.1.3)
├── CSSselect@0.4.1 (domutils@1.4.3, CSSwhat@0.4.7)
└── htmlparser2@3.8.2 (domelementtype@1.1.3, domutils@1.5.1, entities@1.0.0, dom handler@2.3.0, readable-stream@1.1.13)
[irteam@CGDLUIT7501 lesson2]$ rm index.js
[irteam@CGDLUIT7501 lesson2]$ vi index.js
[irteam@CGDLUIT7501 lesson2]$ node index.js
执行结果:
[{"title":"详细阅读 Node.js异步特性初体验","href":"http://www.daliane.com/node_js_yi_bu_te_xing_chu_ti_yan/"},{"title":"详细阅读 node.js的package.json以及外部模块","href":"http://www.daliane.com/node_js_de_package_json_yi_ji_wai_bu_mo_kuai/"},{"title":"详细阅读 node.js最简单的 express 应用","href":"http://www.daliane.com/node_js_zui_jian_dan_de_express_ying_yong/"},{"title":"详细阅读 如何在linux上搭建 Node.js 开发环境","href":"http://www.daliane.com/ru_he_zai_linux_shang_da_jian_node_js_kai_fa_huan_jing/"},{"title":"详细阅读 AngularJS学习笔记之全文检索","href":"http://www.daliane.com/angularjs_xue_xi_bi_ji_zhi_quan_wen_jian_suo/"},{"title":"详细阅读 东北人就是牛","href":"http://www.daliane.com/dong_bei_ren_jiu_shi_niu/"},{"title":"详细阅读 遇到危险先逃跑的未必不是英雄","href":"http://www.daliane.com/yu_dao_wei_xian_xian_tao_pao_de_wei_bi_bu_shi_ying_xiong/"},{"title":"详细阅读 原谅那个背后开枪的人","href":"http://www.daliane.com/yuan_liang_na_ge_bei_hou_kai_qiang_de_ren/"},{"title":"详细阅读 AngularJS 学习笔记之第一张AngularJS 模板","href":"http://www.daliane.com/angularjs_xue_xi_bi_ji_zhi_di_yi_zhang_angularjs_mo_ban/"},{"title":"详细阅读 AngularJS 学习笔记之环境搭建","href":"http://www.daliane.com/angularjs_xue_xi_bi_ji_zhi_huan_jing_da_jian/"}]
记得好好看看 superagent 的 API,它把链式调用的风格玩到了极致。