TL;DR
-
feedparser.parse()
の結果は返り値のbozo
を見るのが一番手っ取り早い。0の時だけパース成功 - パース成功してなければ
bozo_execption
を見ておけば良い
動機
>>> import feedparser
>>>
>>> resp1 = feedparser.parse('http://qiita.com/tags/python/feed')
>>> type(resp1)
<class 'feedparser.FeedParserDict'>
>>>
>>> resp2 = feedparser.parse('http://qiita.com/tags/python1/feed')
>>> type(resp2)
<class 'feedparser.FeedParserDict'>
feedparser.parse()
は、指定したURLがなんであれfeedparser.FeedParserDict
を返します。
それだとちょっと不便なので、ちょっとこの中身を少しみてみることにしました。
調べてみるもの
変数情報
変数名 | URL | |
---|---|---|
resp1 | http://qiita.com/tags/python/feed | 普通のRSSフィード |
resp2 | http://qiitta.com/tags/python | RSSフィードではない |
resp3 | http://qiita.com/tags/python1/feed | 200以外のステータスコード |
resp4 | http://qiitta.com/tags/python/feed | 存在しないドメイン |
対象
- FeedParserDictのキー
- 共通するキーは何か?
調べてみる
キーを調べる
>>> resp1.keys()
dict_keys(['bozo', 'encoding', 'status', 'etag', 'href', 'entries', 'version', 'namespaces', 'feed', 'headers'])
>>>
>>> resp2.keys()
dict_keys(['bozo', 'encoding', 'status', 'bozo_exception', 'etag', 'href', 'entries', 'version', 'namespaces', 'feed', 'headers'])
>>>
>>> resp3.keys()
dict_keys(['bozo', 'encoding', 'bozo_exception', 'status', 'href', 'entries', 'version', 'namespaces', 'feed', 'headers'])
>>>
>>> resp4.keys()
dict_keys(['bozo', 'entries', 'feed', 'bozo_exception'])
>>>
思いのほか、保持しているキーがバラバラです。bozo
, entries
のみが共通しています。
共通しているキーの中身
>>> resp1.bozo
0
>>> resp1.entries
[{'summary': '<p>第8章ではグラフィカルモデルについて説明されています。グラフィカルモデルとは、確率変数やモデルのパラメータなどの関係を図式的に表現する方法です
# 略
}]
>>>
>>> resp2.bozo
1
>>> resp2.version
''
>>> resp2.entries
[]
>>>
>>> resp3.bozo
1
>>> resp3.version
''
>>> resp3.entries
[]
>>>
>>> resp4.bozo
1
>>> resp4.entries
[]
>>>
この時点で、bozo
が0の時のみ、RSSフィードとしてパースに成功したとみることができます。
本来の主目的だけ見ればこれでほぼほぼ完了なのですが、もうちょっと掘り下げます。
パース失敗勢の構造を見る
パースに成功している結果については何も考えずにentries
いじってればいいので、ここから先はパース失敗のエラーハンドリングを目的に、どんな情報が取れるかを見にいこうと思います。
bozo_exception の存在
resp1,resp2を比較すると、どちらもリクエストに成功はしているからか、status
やheaders
などのHTTPっぽいキーが見て取れます。
そんな中、resp2のみに存在するキーがありました。それがbozo_exception
です。
>>> resp2.bozo_exception
SAXParseException('undefined entity',)
そのまんまなメッセージが入っていました。これを見れば概ね問題なさそうです。
>>> resp3.bozo_exception
NonXMLContentType('text/html; charset=utf-8 is not an XML media type',)
>>>
>>> resp4.bozo_exception
URLError(gaierror(8, 'nodename nor servname provided, or not known'),)
>>>
他のrespも見るとこんな感じ。中の文字列だけ出すのが面倒なのが欠点。
あと、resp3
は404 Not Found
にも関わらず、パースしようとしているので、statusもあるなら合わせて見るのがよさげです。