摘要:因為這里用到了異步編程的事件監(jiān)聽,所有的動作都是異步操作,如果通過上述兩個辦法取出的值都是。但需要注意,在調(diào)用的地方也需要異步編程編碼問題在抓取非英文網(wǎng)頁時,總會遇到編碼問題,中文也不例外。
node-feedparser
這篇文章是我學習node-feedparser的時候所寫的,前半部分是翻譯了node-feedparser在github上的原文(英語不好,如果翻譯有誤,還請見諒。),當中也夾雜了一些自己解釋;后半部分的實戰(zhàn)是我結(jié)合 compressed.js ,同時自己在實際運用中的小結(jié),現(xiàn)在拿出來和大家分享,希望大家給予指正。
文章信息時間 / 2017年3月9日
版本號
Node.js: v6.10.0
node-feedparser: v2.1.0
request: v2.79.0
iconv-lite: v0.4.15
項目地址 / https://github.com/danmactoug...
目錄Feedparser 基于Node.js的RSS,Atom,RDF強勁解析器
如何安裝
用法
feedparser可選參數(shù)
例子
API
feedparser解析后能得到什么?
meta屬性列表
article屬性列表
貢獻
License
實戰(zhàn)
處理數(shù)據(jù)
取得數(shù)據(jù)
編碼問題
錯誤捕捉
Feedparser 基于Node.js的RSS,Atom,RDF強勁解析器Feedparser是一個基于基于Node.js的強勁解析器,可以解析包括RSS,Atom和RDF信息
它有一對特性是你在其他的Feed解析器中不常見的:
它可以解析一些相對URL鏈接(例如Tim Bray"s "ongoing"這個Feed)
它可以正確地解析一些XML命名空間(包含那些非常規(guī)的Feed——用主要的一些Feed元素來定義的非常規(guī)命名空間)
說明:對第二條的理解是,通常Feed的XML命名是固定的一些標簽,但是Feedparser同樣可以對一些非常規(guī)的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 () { // 此時已經(jīng)獲取到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可選參數(shù)
normalize:設(shè)置false讓Feedparser的默認值失效。無論這個Feed的形式,這個參數(shù)都能將其解析成一個包含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:設(shè)置false讓Feedparser的默認值失效。讓每一個Feed的article信息都加入Meta信息。個人建議可以設(shè)置為true,一般來說,每個Feed的Meta信息都是唯一的,而article信息不同,只要第一次獲取Meta后,就可以只需要article信息。
feedurl:Feed的URL地址。FeedParser能非常優(yōu)秀地處理相對url,但是一些Feed在使用相對url時,并不聲明xml:base信息。盡管feedparser非常有效,但是在我們處理feed和嘗試著處理這些相對url之前,我們?nèi)匀徊荒苤纅eed的url。如果我們發(fā)現(xiàn)了feed的url,我們將會返回并處理那些我們已經(jīng)得到的相對url,但這將會消耗一段時間(并非很長)。如果你想要確信我們不對相對url進行預(yù)處理(或者feedparser無法處理相對url),你應(yīng)該設(shè)置feedurl選項,否則,你就當沒看見過它吧~
resume_saxerror:設(shè)置false讓Feedparser的默認值失效。這個選項能夠拋出error中的SAXError錯誤,并自動進行后續(xù)的解析。在我的測試中,SAXErrors并不常錯誤,所以開啟這個選項通常對你很有幫助。如果你想要完全掌握和處理錯誤,并在任意點中止解析feed的話,可以嘗試用這個選項。
例子在這里查看例子 examples 。
API 轉(zhuǎn)換 StreamFeedparser是一個stream轉(zhuǎn)換器(關(guān)于stream你可以在nodejs官網(wǎng)閱讀),從XML文件轉(zhuǎn)換為Javascript的objects對象。
每一個可讀的區(qū)塊都是一個對象,這個對象代表feed中的article信息。
發(fā)出的項目meta - 被解析后,稱作feed的 meta
error - 任何時候Feedparser發(fā)出的錯誤(包括SAXError, Feedparser error等)
feedparser解析后能得到什么?Feedparser對每一個Feed都會解析出 meta 和一個或更多的 articles。
不論Feed的形式如何, meta 和每一個 article 都包含一個RSS2.0規(guī)范同時加上規(guī)范化后的屬性的信息流。舉個例子,一個Atom feed會有一個 meta.description 屬性,但是同樣會有一個 meta["atom:subtitle"] 屬性。
這個規(guī)范化后的屬性是用于向用戶提供一個規(guī)范的接口——當你不知道feed的形式,或者搞不清不同feed形式之間的差異時,用這個接口就可以方便獲取feed信息。不過當你需要原始信息的時候會依然會保留給你使用。此外,F(xiàn)eedparser還提供了一些大眾化的命名空間擴展,例如 itunes , media , feedburner 和 pheedo 這些擴展。舉例:如果一個feed的article同時包含了 itunes:image 或 media:thumbnail ,那么這兩個的url地址都會保存到article的 image.url 屬性中。
所有的屬性都會進行初始化,設(shè)置為 null (空數(shù)組或者空對象都會有恰當?shù)膶傩裕?。這個能夠節(jié)省你很多時間來檢查屬性是否為 undefined ,例如,當你使用jade模板的時候。
除此之外,所有的屬性(包含命名空間)都使用小寫字母("xmlUrl" and
"pubDate"仍然提供向下兼容)。“好用”取代了“原生”——衷心希望你能不必為駱駝拼寫法而煩惱。
如果你設(shè)置normalize為true,那么 meta 和 article 的 title 和 description 屬性都會將HTML標簽剝離。如果你需要這些HTML元素,你可以從 meta["atom:subtitle"]["#"] 這個屬性取得。
meta屬性列表title
description
link (網(wǎng)站鏈接)
xmlurl
date (最近的日期)
pubdate (原始出版日期)
author
language
image (一個對象,包含 url 和 title 屬性)
favicon (favicon的鏈接——只提供給Atom feeds)
copyright
generator
categories (一個字符串數(shù)組)
article屬性列表title
description (通常是完整的標題內(nèi)容)
summary (通常是文章摘錄)
link
origlink
permalink
date
pubdate
author
guid
comments
image
categories
source
enclosures
meta
貢獻在這里查看所有代碼 -> contributors。
License(The MIT License)
實戰(zhàn) 處理數(shù)據(jù)feedparser.on("readable", function() { var item; while (item = this.read()) { //一般我們在這里獲取數(shù)據(jù),在上面提到的,feedparser一共會輸出兩種信息,一種是規(guī)范化后的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將上述的數(shù)據(jù)從函數(shù)中取出,也無法通過在外定義變量,在內(nèi)賦值取出。因為這里用到了異步編程的事件監(jiān)聽,所有的動作都是異步操作,如果通過上述兩個辦法取出的值都是undefined。那么如何取出這些數(shù)據(jù)?這里有兩個辦法:
取得數(shù)據(jù)因為feedparser使用的是異步編程的辦法,所以無法通過常規(guī)方法取出值,不過仍然有以下兩種辦法:
直接在函數(shù)中進行操作
使用Promise封裝
/* * 在函數(shù)中直接進行操作不再演示 * 這里主要演示Promise封裝 */ new Promise((resolve, reject)=>{ //這里是一些request操作代碼,暫時省略 feedparser.on("readable", function() { var item; while (item = this.read()) { resolve(item); } }).then((result)=>{ //在這里可以用then繼續(xù)操作 console.log(result.title); //也可以return一個Promise對象,并在其他地方調(diào)用這個Promise。 //但需要注意,在調(diào)用Promise的地方也需要異步編程 return result; }).catch((err)=>{ console.log(err); });編碼問題
在抓取非英文網(wǎng)頁時,總會遇到編碼問題,中文也不例外。比如新浪新聞的編碼是"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可以直接調(diào)用 .pipe(feedparser);
因為 request 和 feedparser 之間的通訊是通過stream流的,而 iconv-lite 正好又有對于Stream流的API接口,所以直接調(diào)用即可。如果感興趣或者有需要的同學還可以去查看 iconv-lite 的官方文檔查看其它的方法。
錯誤捕捉在整個抓取Feed的過程中,會遇到很多的錯誤,如何處理這些錯誤?這里借鑒一下官方文檔所提到的 compressed.js 中的方法,它將所有的錯誤處理寫成一個函數(shù),然后在每次事件監(jiān)聽的地方,調(diào)用處理錯誤函數(shù)即可完成。
//錯誤處理函數(shù): function done(err) { if (err) { console.log(err, err.stack); return process.exit(1); } process.exit(); } //事件監(jiān)聽調(diào)用done // ...省略 req.on("error", done); // ...省略 feedparser.on("error", done); feedparser.on("end", done); feedparser.on("readable", function() { // ...省略 });
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/86839.html
摘要:由于近期學業(yè)繁重,所以我就不說廢話了,直接上代碼樸素貝葉斯進行文本詞匯分類詞表到向量的轉(zhuǎn)換創(chuàng)建實驗樣本,返回的是進行詞條切分后的文檔集合,還有一個類別標簽侮辱性的非侮辱性的代表侮辱性文字代表正常言論創(chuàng)建一個包含在所有文檔中出現(xiàn)的不重復的詞的 由于近期學業(yè)繁重QAQ,所以我就不說廢話了,直接上代碼~ 樸素貝葉斯進行文本詞匯分類 from numpy import * #詞表到向量的轉(zhuǎn)換...
摘要:前端每周清單年度總結(jié)與盤點在過去的八個月中,我?guī)缀踔蛔隽藘杉?,工作與整理前端每周清單。本文末尾我會附上清單線索來源與目前共期清單的地址,感謝每一位閱讀鼓勵過的朋友,希望你們能夠繼續(xù)支持未來的每周清單。 showImg(https://segmentfault.com/img/remote/1460000010890043); 前端每周清單年度總結(jié)與盤點 在過去的八個月中,我?guī)缀踔蛔隽?..
閱讀 1640·2021-11-04 16:10
閱讀 3094·2021-09-30 09:48
閱讀 2917·2019-08-29 11:31
閱讀 1655·2019-08-28 18:22
閱讀 3316·2019-08-26 13:44
閱讀 1415·2019-08-26 13:42
閱讀 2925·2019-08-26 10:20
閱讀 840·2019-08-23 17:00