这篇文章是我学习node-feedparser的时候所写的,前半部分是翻译了node-feedparser在github上的原文(英语很差,若是翻译有误,还请见谅。),当中也夹杂了一些本身解释;后半部分的实战是我结合 compressed.js
,同时本身在实际运用中的小结,如今拿出来和你们分享,但愿你们给予指正。html
时间 / 2017年3月9日node
版本号git
Node.js: v6.10.0github
node-feedparser: v2.1.0npm
request: v2.79.0编程
iconv-lite: v0.4.15api
项目地址 / https://github.com/danmactoug...数组
Feedparser 基于Node.js的RSS,Atom,RDF强劲解析器bash
如何安装异步
用法
feedparser可选参数
例子
API
feedparser解析后能获得什么?
meta属性列表
article属性列表
贡献
License
实战
处理数据
取得数据
编码问题
错误捕捉
Feedparser是一个基于基于Node.js的强劲解析器,能够解析包括RSS,Atom和RDF信息
它有一对特性是你在其余的Feed解析器中不常见的:
它能够解析一些相对URL连接(例如Tim Bray's "ongoing"这个Feed)
它能够正确地解析一些XML命名空间(包含那些很是规的Feed——用主要的一些Feed元素来定义的很是规命名空间)
说明:对第二条的理解是,一般Feed的XML命名是固定的一些标签,可是Feedparser一样能够对一些很是规的XML进行解析,这就是强大之处。
npm install feedparser
这个例子能简要地示范feedparser的基本概念:
请注意在学习基本的示范的同时,也要学习简化的范例compressed.js文件,这样也可以让你更全面地开展工做。
var FeedParser = require('feedparser'); var request = require('request'); // 须要引入一个request,用于抓取Feed var req = request('http://somefeedurl.xml') var feedparser = new FeedParser([options]); req.on('error', function (error) { // 解决任何的request请求错误 // 这个是request包的错误提示 }); req.on('response', function (res) { var stream = this; // 这里的this是req(所请求request文件),是stream文件类型 if (res.statusCode !== 200) { this.emit('error', new Error('Bad status code')); } else { stream.pipe(feedparser); } }); feedparser.on('error', function (error) { // 处理feedparser的错误 // 这个是feedparser包的错误提示 }); feedparser.on('readable', function () { // 此时已经获取到Feed信息,在这里能够进行你的操做了 var stream = this; // 这里的this是feedparser, 也是stream文件类型 var meta = this.meta; // 注意:这个meta是在feedparser的实例中一直能够得到。 //Meta实际上是RSS等一些的元信息,在后面会介绍到,通常来讲Meta信息都是重复的。 var item; while (item = stream.read()) { console.log(item); //在这里输出每一条Feed信息。 } });
normalize
:设置false
让Feedparser的默认值失效。不管这个Feed的形式,这个参数都能将其解析成一个包含RSS2.0格式,正确属性的对象。序列化后的形式如如下所示(只进入第一层):
//经过bash输出: 属性名:rss:@ 值:[object Object] 属性名:rss:title 值:[object Object] 属性名:rss:link 值:[object Object] 属性名:rss:author 值:[object Object] 属性名:rss:guid 值:[object Object] 属性名:rss:category 值:[object Object] 属性名:rss:pubdate 值:[object Object] 属性名:rss:comments 值:[object Object] 属性名:rss:description 值:[object Object] 属性名:meta 值:[object Object]
addmeta
:设置false
让Feedparser的默认值失效。让每个Feed的article信息都加入Meta信息。我的建议能够设置为true,通常来讲,每一个Feed的Meta信息都是惟一的,而article信息不一样,只要第一次获取Meta后,就能够只须要article信息。
feedurl
:Feed的URL地址。FeedParser能很是优秀地处理相对url,可是一些Feed在使用相对url时,并不声明xml:base
信息。尽管feedparser很是有效,可是在咱们处理feed和尝试着处理这些相对url以前,咱们仍然不能知道feed的url。若是咱们发现了feed的url,咱们将会返回并处理那些咱们已经获得的相对url,但这将会消耗一段时间(并不是很长)。若是你想要确信咱们不对相对url进行预处理(或者feedparser没法处理相对url),你应该设置feedurl
选项,不然,你就当没看见过它吧~
resume_saxerror
:设置false
让Feedparser的默认值失效。这个选项可以抛出error
中的SAXError
错误,并自动进行后续的解析。在个人测试中,SAXErrors
并不常错误,因此开启这个选项一般对你颇有帮助。若是你想要彻底掌握和处理错误,并在任意点停止解析feed的话,能够尝试用这个选项。
在这里查看例子 examples
。
Feedparser是一个stream转换器(关于stream你能够在nodejs官网阅读),从XML文件转换为Javascript的objects对象。
每个可读的区块都是一个对象,这个对象表明feed中的article信息。
meta
- 被解析后,称做feed的 meta
error
- 任什么时候候Feedparser发出的错误(包括SAXError, Feedparser error等)
Feedparser对每个Feed都会解析出 meta
和一个或更多的 articles
。
不论Feed的形式如何, meta
和每个 article
都包含一个RSS2.0规范同时加上规范化后的属性的信息流。举个例子,一个Atom feed会有一个 meta.description
属性,可是一样会有一个 meta['atom:subtitle']
属性。
这个规范化后的属性是用于向用户提供一个规范的接口——当你不知道feed的形式,或者搞不清不一样feed形式之间的差别时,用这个接口就能够方便获取feed信息。不过当你须要原始信息的时候会依然会保留给你使用。此外,Feedparser还提供了一些大众化的命名空间扩展,例如 itunes
, media
, feedburner
和 pheedo
这些扩展。举例:若是一个feed的article同时包含了 itunes:image
或 media:thumbnail
,那么这两个的url地址都会保存到article的 image.url
属性中。
全部的属性都会进行初始化,设置为 null
(空数组或者空对象都会有恰当的属性)。这个可以节省你不少时间来检查属性是否为 undefined
,例如,当你使用jade模板的时候。
除此以外,全部的属性(包含命名空间)都使用小写字母("xmlUrl" and
"pubDate"仍然提供向下兼容)。“好用”取代了“原生”——衷心但愿你能没必要为骆驼拼写法而烦恼。
若是你设置normalize为true,那么 meta
和 article
的 title
和 description
属性都会将HTML标签剥离。若是你须要这些HTML元素,你能够从 meta['atom:subtitle']['#']
这个属性取得。
title
description
link (网站连接)
xmlurl
date (最近的日期)
pubdate (原始出版日期)
author
language
image (一个对象,包含 url
和 title
属性)
favicon (favicon的连接——只提供给Atom feeds)
copyright
generator
categories (一个字符串数组)
title
description (一般是完整的标题内容)
summary (一般是文章摘录)
link
origlink
permalink
date
pubdate
author
guid
comments
image
categories
source
enclosures
meta
在这里查看全部代码 -> contributors。
(The MIT License)
feedparser.on('readable', function() { var item; while (item = this.read()) { //通常咱们在这里获取数据,在上面提到的,feedparser一共会输出两种信息,一种是规范化后的RSS2.0,另外一种是原有的。 //原有信息的获取:(推荐这种) console.log(item.meta.title); console.log(item.title); //RSS2.0信息的获取: console.log(item['meta']['rss:title']['#']); console.log(item['rss:title']['#']); } });
须要注意的是你没法经过return将上述的数据从函数中取出,也没法经过在外定义变量,在内赋值取出。由于这里用到了异步编程的事件监听,全部的动做都是异步操做,若是经过上述两个办法取出的值都是undefined。那么如何取出这些数据?这里有两个办法:
由于feedparser使用的是异步编程的办法,因此没法经过常规方法取出值,不过仍然有如下两种办法:
直接在函数中进行操做
使用Promise封装
/* * 在函数中直接进行操做再也不演示 * 这里主要演示Promise封装 */ new Promise((resolve, reject)=>{ //这里是一些request操做代码,暂时省略 feedparser.on('readable', function() { var item; while (item = this.read()) { resolve(item); } }).then((result)=>{ //在这里能够用then继续操做 console.log(result.title); //也能够return一个Promise对象,并在其余地方调用这个Promise。 //但须要注意,在调用Promise的地方也须要异步编程 return result; }).catch((err)=>{ console.log(err); });
在抓取非英文网页时,总会遇到编码问题,中文也不例外。好比新浪新闻的编码是"utf-8",可是腾讯新闻的编码是"gb3212"。feedparser虽然强大,但不负责解决这些问题,这个时候须要咱们引入 iconv-lite
,来解决编码问题。
var url = "http://www.example.xml"; var req = request(url); var feedparser = FeedParser(); var encode = 'utf-8'; req.on('response', function (res) { console.log(res.statusCode); // 200 console.log(res.headers['content-type']); // 'image/png' }).pipe(iconv.decodeStream(encode)) //在iconv-lite能够直接调用 .pipe(feedparser);
由于 request
和 feedparser
之间的通信是经过stream流的,而 iconv-lite
正好又有对于Stream流的API接口,因此直接调用便可。若是感兴趣或者有须要的同窗还能够去查看 iconv-lite
的官方文档查看其它的方法。
在整个抓取Feed的过程当中,会遇到不少的错误,如何处理这些错误?这里借鉴一下官方文档所提到的 compressed.js
中的方法,它将全部的错误处理写成一个函数,而后在每次事件监听的地方,调用处理错误函数便可完成。
//错误处理函数: function done(err) { if (err) { console.log(err, err.stack); return process.exit(1); } process.exit(); } //事件监听调用done // ...省略 req.on('error', done); // ...省略 feedparser.on('error', done); feedparser.on('end', done); feedparser.on('readable', function() { // ...省略 });