檢查 OPML 的 feed 是否有效

過去我從 Bloglines 跳槽到 Google Reader ,原因就不講了,在使用 Google Reader 幾年下來,我覺得 Google Reader 的優點莫過於優良的搜尋、能以 Star 保存重要的 item、讀過的 item 才會 Mark(那個 Friends’ shared items 實在很雞肋);而缺點則常是介面上的,諸如 feed 的標題不會更新、沒有手動排序、List View 不好用、不能針對單一的 feed 設定等。反過來說,Bloglines 就沒有 Star,對讀過的 item 的 mark 上做的也沒有 Google Reader 好。

除了上述那些缺點之外,Google Reader 還有一個不太好的地方,他不會提醒 feed 已經失效了,這點 bloglines 就會用 [!] 來告訴你。那我近 300 個 feed 到底有哪些是失效的?Google Reader 不會和你說,就只能自己手動檢查了。我寫了一個小程式來判斷 Google Reader 輸出的 OPML 有哪些 feed 還活著。

程式碼很簡單,主要是用 XML::OPMLLWP::Parallel,如果你很在意效能,我想你可能還需要對 LWP::Parallel 的參數略做調整。

#!/usr/bin/perl -w

use strict;
use XML::OPML;
use LWP::Parallel;
use encoding "utf8";

my %feeds_hash;

&main();

sub main {
    my $opml = new XML::OPML;
    $opml->parse ($ARGV[0]) or die $!;

    foreach my $child (@{$opml->outline}) {
        foreach my $x ($child) {
            child_traverse($x);
        }
    }

    my $pua = new LWP::Parallel::UserAgent;
    $pua->timeout (10);
    $pua->redirect (1);

    foreach (keys %feeds_hash) {
        $pua->register(HTTP::Request->new('GET', $_));
    }

    my $entries = $pua->wait();

    foreach (keys %$entries) {
        my $res = $entries->{$_}->response;

        if ($res->code != 200) {
            my $feed_text =  defined $feeds_hash{$res->request->url} ? 
                $feeds_hash{$res->request->url} : "";
            print $feed_text,
            ": feed url = ",$res->request->url," was ",
            $res->code,": ",$res->message,"\n";
        }
    }
}

sub child_traverse {
    my $x = shift;

    if (defined(${$x}{"type"}) and ${$x}{"type"} eq "rss" ){
        $feeds_hash{${$x}{"xmlUrl"}} = ${$x}{"text"};
    } else {
        foreach (values %{$x}) {
            child_traverse($_) if (ref($_) eq "HASH");
        }
    }
}

Known Issues

  1. 遇到 Bad Behavior 會吐 403
  2. 在 redirect 模式下,redirect 出去會造成 $feeds_hash{$res->request->url} 會抓不到值
  3. response code 200 不代表是有效的 rss,如 pixnet 現在會回應「No Open」
  4. 不能處理 307 Temporary Redirect
  5. 會吐 Parsing of undecoded UTF-8 will give garbage when decoding…

也許可以用 LWP::Parallel::UserAgent 在 register 時的 callback function 中,用 XML::RSS 來判斷是不是有效的 rss,不過這樣 parsing 下來應該會很慢才是……。也許下一步我會嘗試上面這件事情,還有檢查 outline 的 text(title)和 feed 的 title 是不是相符吧,或者,該換到 beta 看起來很漂亮的 beta.bloglines.com 去。

2 Replies to “檢查 OPML 的 feed 是否有效”

Leave a Reply

Your email address will not be published. Required fields are marked *