feedparser学习与实战——基于Node.js的Feed解析器

时间:2019-09-29
本文章向大家介绍feedparser学习与实战——基于Node.js的Feed解析器,主要包括feedparser学习与实战——基于Node.js的Feed解析器使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

这篇文章是我学习node-feedparser的时候所写的,前半部分是翻译了node-feedparser在github上的原文(英语不好,如果翻译有误,还请见谅。),当中也夹杂了一些自己解释;后半部分的实战是我结合 compressed.js ,同时自己在实际运用中的小结,现在拿出来和大家分享,希望大家给予指正。

文章信息

目录

  • Feedparser 基于Node.js的RSS,Atom,RDF强劲解析器
  • 如何安装
  • 用法
    • feedparser可选参数
  • 例子
  • API
  • feedparser解析后能得到什么?
    • meta属性列表
    • article属性列表
  • 贡献
  • License

  • 实战

    • 处理数据
    • 取得数据
    • 编码问题
    • 错误捕捉

Feedparser 基于Node.js的RSS,Atom,RDF强劲解析器

Feedparser是一个基于基于Node.js的强劲解析器,可以解析包括RSS,Atom和RDF信息

它有一对特性是你在其他的Feed解析器中不常见的:

  1. 它可以解析一些相对URL链接(例如Tim Bray’s “ongoing”这个Feed)

  2. 它可以正确地解析一些XML命名空间(包含那些非常规的Feed——用主要的一些Feed元素来定义的非常规命名空间)

说明:对第二条的理解是,通常Feed的XML命名是固定的一些标签,但是Feedparser同样可以对一些非常规的XML进行解析,这就是强大之处。

如何安装

1
2
npm install feedparser

用法

这个例子能简要地示范feedparser的基本概念:

请注意在学习基本的示范的同时,也要学习简化的范例compressed.js文件,这样也能够让你更全面地开展工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
var FeedParser = require('feedparser');
var request = require('request');
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信息。
}
});

feedparser可选参数

  • normalize:设置false让Feedparser的默认值失效。无论这个Feed的形式,这个参数都能将其解析成一个包含RSS2.0格式,正确属性的对象。序列化后的形式如以下所示(只进入第一层):
1
2
3
4
5
6
7
8
9
10
11
12
//通过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

API

转换 Stream

Feedparser是一个stream转换器(关于stream你可以在nodejs官网阅读),从XML文件转换为Javascript的objects对象。

每一个可读的区块都是一个对象,这个对象代表feed中的article信息。

发出的项目

  • meta - 被解析后,称作feed的 meta
  • error - 任何时候Feedparser发出的错误(包括SAXError, Feedparser error等)

feedparser解析后能得到什么?

Feedparser对每一个Feed都会解析出 meta 和一个或更多的 articles

不论Feed的形式如何, meta 和每一个 article 都包含一个RSS2.0规范同时加上规范化后的属性的信息流。举个例子,一个Atom feed会有一个 meta.description 属性,但是同样会有一个 meta['atom:subtitle'] 属性。

这个规范化后的属性是用于向用户提供一个规范的接口——当你不知道feed的形式,或者搞不清不同feed形式之间的差异时,用这个接口就可以方便获取feed信息。不过当你需要原始信息的时候会依然会保留给你使用。此外,Feedparser还提供了一些大众化的命名空间扩展,例如 itunes , media , feedburnerpheedo 这些扩展。举例:如果一个feed的article同时包含了 itunes:imagemedia:thumbnail ,那么这两个的url地址都会保存到article的 image.url 属性中。

所有的属性都会进行初始化,设置为 null (空数组或者空对象都会有恰当的属性)。这个能够节省你很多时间来检查属性是否为 undefined ,例如,当你使用jade模板的时候。

除此之外,所有的属性(包含命名空间)都使用小写字母(”xmlUrl” and
“pubDate”仍然提供向下兼容)。“好用”取代了“原生”——衷心希望你能不必为骆驼拼写法而烦恼。

如果你设置normalize为true,那么 metaarticletitledescription 属性都会将HTML标签剥离。如果你需要这些HTML元素,你可以从 meta['atom:subtitle']['#'] 这个属性取得。

meta属性列表

  • title
  • description
  • link (网站链接)
  • xmlurl
  • date (最近的日期)
  • pubdate (原始出版日期)
  • author
  • language
  • image (一个对象,包含 urltitle 属性)
  • favicon (favicon的链接——只提供给Atom feeds)
  • copyright
  • generator
  • categories (一个字符串数组)

article属性列表

  • title
  • description (通常是完整的标题内容)
  • summary (通常是文章摘录)
  • link
  • origlink
  • permalink
  • date
  • pubdate
  • author
  • guid
  • comments
  • image
  • categories
  • source
  • enclosures
  • meta

贡献

在这里查看所有代码 -> contributors

License

(The MIT License)

实战

处理数据

1
2
3
4
5
6
7
8
9
10
11
12
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封装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
* 在函数中直接进行操作不再演示
* 这里主要演示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 ,来解决编码问题。

1
2
3
4
5
6
7
8
9
10
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);

因为 requestfeedparser 之间的通讯是通过stream流的,而 iconv-lite 正好又有对于Stream流的API接口,所以直接调用即可。如果感兴趣或者有需要的同学还可以去查看 iconv-lite官方文档查看其它的方法。

错误捕捉

在整个抓取Feed的过程中,会遇到很多的错误,如何处理这些错误?这里借鉴一下官方文档所提到的 compressed.js 中的方法,它将所有的错误处理写成一个函数,然后在每次事件监听的地方,调用处理错误函数即可完成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//错误处理函数:
function (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() {
// ...省略
});

原文:大专栏  feedparser学习与实战——基于Node.js的Feed解析器


原文地址:https://www.cnblogs.com/chinatrump/p/11607349.html