はじめに
この記事は、オールアバウト Advent Calendar 2016の8日目の記事です。
先日は@takkyさんのWelcome to Laravel Voyagerでした。
新卒1年目エンジニアの @amymd が、RSSフィード関係の実装を通して得た知見を共有できればと思います。
導入〜RSSフィード取得に失敗してる!さあどうしよう?
ある日のこと、自分はいつも通り会社に出社し、メールを確認しました。
すると、定期的にRSSを取得している処理がどうやら失敗しているようです。
RSS取得に失敗しているからといえ、この時点では、まだどこに問題があるかわかりません。
RSS取得の処理になにか問題あるかもしれませんし、RSS自体に問題があるのかもしれません。
その問題の切り分けをしていきましょう
エラーログを確認する
基本中の基本ですが、まずはエラーログの内容を確認します。
Logentriesでログの管理を行っているため、サーバにSSHせずともブラウザから簡単にログを確認できます。大変便利です。
This XML document is invalid.等のXMLエラーの場合、RSSに問題があるかもしれません。
プログラムの処理に関するエラーが出ていると、RSSの取得処理に問題があるかもしれません。
まずはログの内容から、どちらの問題なのか目処を付けてみます。
RSSのどこが問題なのか調査する
RSSの問題だと思ったら、まずは該当のRSSをブラウザからアクセスしてみて、何かエラーが出てないか確認してみます。
また、特にブラウザ上では問題なくても、Validatorでチェックするとエラーが出ていることがあります。
上記のURLでXMLに問題があるかチェックすることができます。
RSSのXMLやURL等を貼り付けて調べてみると、具体的にどの行でどのようなエラーが発生しているのかが表示されます。
以下は、自分が遭遇した問題の例をあげます。
例:CDATAセクションの中でCDATAセクションを呼び出していた
CDATAセクションとは、セクション内にマークアップが含まれず文字データのみを取り扱うことを示すものです。
https://msdn.microsoft.com/ja-jp/library/ms256076(v=vs.120).aspx
<![CDATA[An in-depth look at creating applications with XML, using <, >,]]>
このCDATAセクション内に、さらにCDATAセクションが埋め込まれていて、終端の]]>
を誤認識してしまい、その結果下記のようなエラーが出ていました。
error on line 105 at column 3342: Opening and ending tag mismatch: encoded line 0 and script
例:「見えない文字」が原因で「This XML document is invalid.」
This XML document is invalid, likely due to invalid characters.
RSSを取得しようとすると上記のエラーが発生しておりました。
これは、XMLでは有効ではない文字列が含まれている、というエラーです。
原因を特定するために、先ほど示したW3C Validatorを使用してみました。
しかし、そのエラーが発生している行を確認しても、あやしい文字はどこにも含まれていませんでした。
こういう時は、Sublime Textなどのエディタに、その箇所をコピペしてみます(自分はmiというエディタに貼り付けました)。
すると、以下のように「見えない文字」が表示されました。
このエディタ上で上記の文字を削除し、再度RSSを読み込んでみると……正常に取得できました!
原因はどうやらこの「見えない文字」のようです。
なぜこのような見えない文字が含まれてしまうのか
これは一概に「これが原因だ!」とは言い切れないのですが、
個人的な経験からすると、このような「見えない文字」は、OCRにかけたPDFからコピペしてくるときに紛れていたり、Macで作成したPDFをWindowsからコピペするときに紛れていたり、ということが多いような気がします。
それが原因なのかは定かではありませんが……。
他には、制御文字(BackSpaceなど)が原因ということもあるみたいです。
ぱっと見てXMLに問題がなさそうであれば、このような症状を疑うと良いと思います。
RSSを取得する処理に問題がある場合
RSSに特に問題が無いようであれば、RSSを取得する処理に問題があるかもしれません。
その処理を見直してみましょう。
以下は、自分が遭遇した問題の例をあげます。
例:RSS取得の処理に時間が掛かってタイムアウト
自分はLaravelというPHPのWebフレームワークを使用しており、 RSSをパースするLaravelのライブラリとしてFeeds を利用していました。
すると、とあるRSSを取得する際に、表示まで時間が掛かってしまい、下記のようなエラーが出てしまいました。
cURL error 28: Operation timed out after 10000 milliseconds with 0 bytes received
このライブラリでは、内部でSimplePieというRSSやAtomをパースするライブラリを使っており、cURLのデフォルトのタイムアウトの処理時間が10000msec…つまり10秒となっていました。
この設定を書き換えるには、Feedsライブラリを直接書き換える必要があるので、注意する必要があります。
(SimplePieオブジェクトなので $this->simplepie->set_timeout(60)
のようにセットするとタイムアウトの時間を60秒にセットすることができます)
public function make($feed_url = [], $limit = 0, $force_feed = false) {
$this->simplepie = new SimplePie();
$this->simplepie->set_timeout(60); // タイムアウトの秒数を指定
おわりに
今回はRSSが取得できなかったときの問題とその対応例を紹介しましたが、RSSフィードをパースして値を処理する際の問題など、まだまだあるかと思います。
中には、RSSの問題だとわかりつつも、RSSを処理する側でどうにかできたり、逆にRSSを修正しないとどうにもできなかったり…。
今回自分が得た知見が共有されて、少しでもみなさんの開発の一助となれば幸いです。