仙石浩明の日記

2006年5月1日

livedoor blog 生ログ取得スクリプト (2)

昨日書いた「livedoor blog 生ログ取得スクリプト」を使って、 毎日前日の生ログを取得する cron を仕掛けておいたのですが、 月が代わった途端に問題発覚(^^;)。 livedoor blog の生ログって、月単位なのですね。 つまり、生ログを参照するページの URL は、

http://analyzer.livedoor.com/log/raw?page_id=22222&y=2006&m=4

などとなっていますが、「m=4」を指定しない限り 4月分のログは表示されない (今月分のみ表示される)、 という仕様のようです。 livedoor blog の有料プランを始めてから初めての月代わりだったもので...

というわけで、生ログを取得する際に日付を指定できるように修正してみました。

livedoor.pl gcd date 2006-04-30 raw_log 100 -

などと、「date YYYY-MM-DD」ないし「date YYYY-MM」を指定することにより、 生ログを取得する日付ないし月を指定できます。 「raw_log 100 - 」は、生ログ 100ページ分 (2000行) を標準出力 (「 - 」) に出力する、という意味です。

生ログを遡っていく途中で、指定した日付と異なる日付の生ログが得られたら、 それ以上の取得をストップするので、ページ数は多めに指定しておいて大丈夫です。 また、ついでに「ブログのエクスポート(バックアップ)」もサポートしました。

livedoor.pl gcd export_reserve

で、「エクスポートファイルの作成」を行ない、

livedoor.pl gcd export バックアップファイル名

で、エクスポートファイルをダウンロードして 「バックアップファイル名」で保存します。

以上の機能は、 livedoor blog の有料プランを選択していないと使用できませんが、 スタイルシート(CSS)および HTMLのテンプレートの取得は、 ブログのデザインを custom に設定していれば使用できます。

まず、livedoor blog の管理ページで、 「カスタマイズ/管理」-「デザインの設定」を選び、 デザインとして「カスタマイズ」を選択したときの URL を確認します。 例えば

http://cms.blog.livedoor.com/cms/design/edit?blog_id=1600549&id=11111

といった感じの URL になると思います。 「blog_id=1600549」および「id=11111」の数字を、 スクリプト先頭の

"BlogID" => 1600549,
"ID"     => 11111,

の部分に設定しておいて、

livedoor.pl gcd css CSSファイル名

と実行すれば、スタイルシート(CSS) が「CSSファイル名」で保存されます。 「css」の代わりに、 「index_tmpl」「article_tmpl」「category_tmpl」「monthly_tmpl」 を指定すれば、それぞれ「トップページ」「個別記事ページ」 「カテゴリアーカイブ」「月別アーカイブ」の HTMLテンプレートを 保存できます。 一度のスクリプト実行で一括して保存することもできます:

livedoor.pl gcd css blog.css index_tmpl blog.html \
        article_tmpl blog_article.html \
        category_tmpl blog_category.html \
        monthly_tmpl blog_month.html

「スタイルシート(CSS)」を、「blog.css」へ、
「トップページ」を、「blog.html」へ、
「個別記事ページ」を、「blog_article.html」へ、
「カテゴリアーカイブ」を、「blog_category.html」へ、
「月別アーカイブ」を、「blog_month.html」へ、
それぞれ保存します。

livedoor.pl (livedoor blog 生ログ & CSS/テンプレート 取得スクリプト)

#!/usr/bin/perl
use LWP::UserAgent;
use HTTP::Request::Common;
use CGI qw/unescapeHTML/;

%blogs = (
    "gcd" => {
        "User"   => "hiroaki_sengoku",
        "Pass"   => "xxxxxxxx",
        "BlogID" => 1600549,
        "ID"     => 11111,
        "PageID" => 22222,
    },
    "klab" => {
        "User"   => "klab_sengoku",
        "Pass"   => "yyyyyyyy",
        "BlogID" => 1631449,
        "ID"     => 33333,
        "PageID" => 44444,
    },
);

&help unless $_ = shift;
if (exists $blogs{$_}) {
    my $blog = $blogs{$_};
    $User =   $$blog{"User"};
    $Pass =   $$blog{"Pass"};
    $BlogID = $$blog{"BlogID"};
    $ID =     $$blog{"ID"};
    $PageID = $$blog{"PageID"};
} else {
    &help;
}

$ua = new LWP::UserAgent;
$ua->agent("Mozilla/5.0 (Windows; U; Windows NT 5.1; ja)");
$ua->env_proxy();
$ua->cookie_jar( {} );
my $res = $ua->request(POST "http://member.livedoor.com/login/index",
                       [ "livedoor_id" => $User, "PASSWORD" => $Pass,
                         ".next" => "", ".sv" => "" ]);
while (my $type = shift) {
    if ($type eq "date") {
        $_ = shift;
        if (/^(\d\d\d\d)-(\d\d)(?:-(\d\d))?$/) {
            $Year = $1;
            $Month = ($2 + 0);
            $Date = $_;
        } else {
            die "date must be YYYY-MM-DD: $_\n";
        }
    } elsif ($type eq "css" ||
             $type eq "index_tmpl" || $type eq "article_tmpl" ||
             $type eq "category_tmpl" || $type eq "monthly_tmpl") {
        my $file = shift;
        open(OUT, ">$file") || die;
        my $url = "http://cms.blog.livedoor.com/cms/design/edit"
            . "?tmpl=$type&blog_id=$BlogID&id=$ID";
        my $req = new HTTP::Request GET => $url;
        my $res = $ua->request($req);
        if ($res->content =~
            /\<textarea .*name=\"content\" [^\>]*\>([^\<]+)\<\/textarea\>/) {
            my $content = unescapeHTML($1);
            $content =~ s/\r\n/\n/g;
            print OUT $content, "\n";
        }
        close(OUT);
    } elsif ($type eq "raw_log") {
        my $npage = shift;
        ($npage =~ m/^\d+$/ && $npage >= 1) || &help;
        my $file = shift;
        &help unless $file;
        open(OUT, ">$file") || die;
        my $url = "http://analyzer.livedoor.com/log/raw?page_id=$PageID";
        if ($Date) {
            $url .= "&y=$Year&m=$Month";
        }
        my $prepat = '\<td\b[^\>]*\>\<strong\>\<small\>';
        my $postpat = '\<\/small\>\<\/strong\>\<\/td\b[^\>]*\>';
        my $datematch = 0;
        pages: for (my $i=1; $i <= $npage; $i++) {
            my $req = new HTTP::Request GET => "$url&p=$i";
            my $res = $ua->request($req);
            my $datepat = '\d\d\d\d\-\d\d\-\d\d \d\d\:\d\d\:\d\d';
            my $date;
            for (split(/(\<small\>$datepat\<\/small\>)/o, $res->content)) {
                if (/^\<small\>($datepat)\<\/small\>$/o) {
                    $date = $1;
                } elsif (/^\<\/th\>\s*\<\/tr\>\s*/) {
                    my @record;
                    for (split(/\<\/tr\>\s*/, $')) {
                        my $column;
                        if (/$prepat(.*)$postpat/o) {
                            if ($1 eq 'URL') {
                                $column = 0;
                            } elsif ($1 eq 'リファラ') {
                                $column = 1;
                            } elsif ($1 eq 'ブラウザ') {
                                $column = 2;
                            } elsif ($1 eq 'リモートホスト') {
                                $column = 3;
                            } else {
                                die "Unknown column: $_\n";
                            }
                        }
                        if (/\<td\b[^\>]*\>\<small\>(.*)\<\/small\>\<\/td\b[^\>]*\>/){
                            $_ = $1;
                            s/\<\/?a\b[^\>]*\>//g;
                            if (/,/) {
                                s/\"/\"\"/g;
                                $_ = "\"$_\"";
                            }
                            $record[$column] = $_;
                        } elsif (/^\<\/table\>/) {
                            last;
                        } elsif (! /^\<tr\>\s*\<th\b[^\>]*\>/) {
                            die "Unknown format: $_\n";
                        }
                    }
                    if (! defined($Date) || $date =~ /^$Date/) {
                        $datematch = 1;
                        print OUT $date, ",", join(',', @record), "\r\n";
                    } elsif ($datematch) {
                        last pages;
                    }
                }
            }
        }
        close(OUT);
    } elsif ($type eq "export_reserve") {
        my $url = "http://cms.blog.livedoor.com/cms/import/mt/export_reserve";
        my $req = new HTTP::Request GET => $url;
        my $res = $ua->request($req);
        if (! $res->is_success) {
            print STDERR "fail to reserve export";
            exit 1;
        }
    } elsif ($type eq "export") {
        my $file = shift;
        open(OUT, ">$file") || die;
        my $url = "http://cms.blog.livedoor.com/cms/import/mt/export";
        my $req = new HTTP::Request GET => $url;
        my $res = $ua->request($req);
        print OUT $res->content;
        close(OUT);
    } else {
        &help;
    }
}
exit 0;

sub help {
    print STDERR "Usage livedoor <blog> <opt>...\nblog: ",
    join("\n      ", keys %blogs), "\n",
    'opt:  date YYYY-MM
      date YYYY-MM-DD
      css <file>
      index_tmpl <file>
      article_tmpl <file>
      category_tmpl <file>
      monthly_tmpl <file>
      raw_log <n> <file>
      export_reserve
      export <file>
';
    exit 1;
}
Filed under: プログラミングと開発環境 — hiroaki_sengoku @ 08:45

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.