HTTPSサイトからフィードを取得する
自分のブログを SSL/TLS に対応させたらフィードが取得できなくなっていたので,とりあえず応急処置的な方法で修正しました.
feed の取得環境
WordPress の Jetpack に自動パブリサイズ機能はついていますが,あれで Twitter などに投稿すると書き換え前の URL を使われてしまい,これが非常に厄介.Twitter Card が正しく表示されないなどの問題が発生します.そこで自動で feed を取得して Twitter に投稿する BOT を作ってツイートしていました.
Twitter にブログ記事の更新を自動投稿する BOT を作る
ただ,そのことを忘れて SSL/TLS に切り替え,HTTP から HTTPS へのリダイレクトを強制したため,以前のコードでは動かなくなってしまいました.
エラー内容
feed を取得したときのエラーはこのようになっています.
{'feed': {}, 'bozo': 1, 'bozo_exception': URLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)'),), 'entries': []}
ソースコードの詳細
簡単に書くと feed 全体をこんな感じで読み込んでいました.
import feedparser
feed = feedparser.parse('https://blog.mktia.com/feed')
HTTP サイトへの接続なら,これで問題ありません.
対策方法
思いつくのは主に二つです.
- HTTPS に接続しても feed を取得できるようにソースコードを書きかえる
- HTTPS への強制リダイレクトをやめる
Web サーバ側では 80 番ポートも 443 番ポートも開放しているので,強制リダイレクトをやめれば feed が取得できるようになります.
しかし,一つのブログに対して URL が二つに分かれているのはあまり望ましい状況ではありません.よって,できればソースコードで対応したいところです.
応急処置的な対処
Highly discouraged な方法ですが...
import feedparser
import ssl
if hasattr(ssl, '_create_unverified_context'):
ssl._create_default_https_context = ssl._create_unverified_context
feed = feedparser.parse('https://blog.mktia.com/feed')
とりあえずこれで取得できるようになります.
参考:Feedparser.parse() 'SSL: CERTIFICATE_VERIFY_FAILED' | Stack Overflow
ところで,このエラー何か見覚えあるような気がしたんですが,HTML 取得の際にも似たようなものが出たことがありました.
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:645)>
これは User-Agent を指定することによって解決できたのですが,ここから推察するに (概念的に) プログラムではなくユーザーとして接続すれば feed の取得に失敗しないのでは?と.SSL/TLS 適用後も feedly で問題なく取得できていますし.で,Chrome を指定して接続を試みて失敗しました.(あれ...?)
最後に
feedparse に関する記事の少なさ.Qiita でも 5 件,Stack Overflow もほとんどなし.もしかして Python で取得するなら,もっといい方法があるんです?