相変わらずMagpieRSSを使ってる。
色々と問題を抱えながらも、使い続けてやってる。
もっといいライブラリもあるみたいだけど、ライブラリ入れ替えちまったらデバッグが大変すぎ。

で、まだまだ使い続けるので致命的な問題を色々と調査。わかったことをメモしておく(バージョンは0.72)。

MagpieRSSが読み込める最大ファイルサイズは?

ある日から、巨大なRSSが最後まで読み込めていないことが判明。
巨大ってのは数百Kバイト以上。具体的には500Kバイトぐらいが上限のような現象が起こるが、MagpieのメッセージもPHPのエラーも出力されない。
ってことは、ライブラリのバグか、ライブラリが上限を制御しているってことになる。

ネットで調べてもわからなかったが、「Snoopy.class.inc」にちゃんと設定箇所があった。
rss_parse.incでもrss_cache.incでもrss_fetch.inc でもなく、「Snoopy.class.inc」ってのが罠っぽい。

Snoopy.class.incで「$maxlength」を検索し、

var  $maxlength = 500000;   // max return data length (body)
$maxlengthの値を増やしてやればいい。
なお、同一サーバ内での読み込みではそんなに問題ないけど、他サーバから大量のRSSを読み込む場合はプロバイダの制限にも注意を。

MagpieRSSは<enclosure>要素が読めない?

そもそもMagpieRSSがRSS2.0に対応してない?という話も聞こえるが、一応対応はしてる。
ただし、最小限の要素しか定義されていないために、<enclosure>要素が読めないようだ。
詳細は「KoshigoeBLOG」さんの「MagpieRSSは属性をうまく扱えないらしい」を参照していただくとして、要は「自分で定義せよ」ってことらしい。

rss_parse.incで以下のコメントを探し、
// if we're in the default namespace of an RSS feed,
//  record textinput or image fields

その前か後ろに<enclosure>のエントリーを以下のように追加する。

// enclosure fields

elseif ( 
$this->feed_type == RSS and
   $el == 'enclosure' )
{
   $this->current_item['enclosure'] = $attrs;
}

// if we're in the default namespace of an RSS feed,
//  record textinput or image fields

これだけで<enclosure>がパースされるようになる。
呼び出し側では、たとえばURLを取り出したいときは以下のように記述する。

foreach ($rss->items as $item ) {

  $title = $item['title'];
 ...
  $link = $item['link'];
  $img_url = $item['enclosure']['url'];
 ...

サイトによっては、rss_parse.incへの記述追加には触れずに、呼び出し方法を$item['enclosure'][0]['url'];と説明していたりするが、もしかしたらもっと新しいバージョンが存在するのかもしれない。

MagpieRSSのバージョン0.72は文字化けする?

文字化けが多いという情報を見かけるし、以前私自身もあまりの文字化けのひどさにバージョンダウンしたことがあったが、今回、日本語文字変換を全面的に見直したところ、文字化けトラブルは確実に少なくなった。

・MAGPIE_OUTPUT_ENCODING
0.72では日本語コード変換をライブラリ内でやってくれる。以前のバージョン向けの解説ではアプリ側でコード変換するソース例ばかりだから、古いソースのままでは二重にコード変換してしまう。
で、呼び出す側のアプリの先頭で、使用する日本語コードをMAGPIE_OUTPUT_ENCODINGで定義しておく。
define('MAGPIE_OUTPUT_ENCODING', 'UTF-8');

よくライブラリ内のデフォルト定義を書き換える話が出てくるが、アプリ側でdefineするのが筋だろうな。

・mb_convert_encoding()は使わない
今までmb_convert_encoding()を使ってコード変換していたら、削除してしまう。変換元をautoにしておけば残しておいても問題なさそうだが、無用の長物だ。

・UTF-8に統一
なんだかんだでぜ〜んぶUTF-8に統一するのが一番トラブルが少ないような気がする。特にpreg_replace()などの日本語を含む正規表現がうまくいく。MagpieRSSの問題よりも。UTF-8を避けていたことで起こる問題が多かったかも。

キャッシュを強制的に更新するには

自サイトに作成したRSSファイルを更新したときなど、更新直後にキャッシュも更新したいことがある。
define("MAGPIE_CACHE_AGE", 1); ってやれば1秒後には更新されるわけだけど、同じスクリプト内で外部のRSSも読み込んでいる場合は、キャッシュを長くしておきたいわけで。
やり方がわからんので、fetch_rss()のときにキャッシュ更新を指示できるようにrss_fetch.incを改造した。


rss_fetch.incで以下のように赤字部分を修正・追加。


function fetch_rss ($url,$force_c) {
...
else {
    // Flow
    // 1. check cache
    // 2. if there is a hit, make sure its fresh
    // 3. if cached obj fails freshness check, fetch remote
    // 4. if remote fails, return stale object, or error

    if ($force_c == 0) {
      $cache_age = MAGPIE_CACHE_AGE;
    } else {
      $cache_age = 1; // 1 を $force_c に書き換えれば任意のキャッシュ期間指定になる
    }

    $cache = new RSSCache( MAGPIE_CACHE_DIR, $cache_age );
...

呼び出し側では、キャッシュ更新を伴うRSSの fetch_rss() 呼び出しで 0 より大きい値を付け加える。

なお、すでに作成されているキャッシュファイルは一旦削除してから実行すること。
$rss = fetch_rss($url ,1);
こんなことしなくても一発で更新できるオプションがあればいいんだけどねぇ・・・