StackStockBooksのエクスポートしたCSVをPerl使って読書メーターにインポートする

読書メーターはインポート機能が無いので他の蔵書管理から移るのが めんどくさいのですが,Perl の WWW::Mechanize 使ってさくっとやる方法. Perl 分かんない人は下手に手を出すと読書メーターがひどいことになるので注意 w Perl 分かる人は適当に加工して使うといいんじゃないでしょうか.

できあがった読書メーターはこちら.reverse 入れ忘れたので読み終えた本以外, 逆順だけど,まぁどうでもいいや.

SSBCSV モジュール

まずは StackStockBooks のエクスポート機能で CSV ファイルを書き出します. このファイルには ISBN とか書名とかいろんな情報が入ってますが,基本的に 使うのは「ISBN」「状態」「日付」で良いと判断しています.

あとは Perl で読み込みます.Text::CSV::Simple というモジュールを使うと ハッシュで取得することができるので,ソースが読みやすくなります. 細かいことはソース見て下さい.

package SSBCSV;

use Switch;
use Text::CSV::Simple;

sub new{
    my $class = shift;
    my $file = shift;
    my $self = {
        csv_parser => Text::CSV::Simple->new({binary => 1}),
        filename => $file,
    };
    return bless $self, $class;
}

sub get{
    my $self = shift;
    $self->{csv_parser}->want_fields(0, 6, 7);
    $self->{csv_parser}->field_map(qw/isbn state date/);
    my @list = $self->{csv_parser}->read_file($self->{filename});
    shift @list;

    foreach my $book(@list){
        switch($book->{state}){
            case 'もう読み終えた' {$book->{state} = 'read'}
            case 'いま読んでいる' {$book->{state} = 'reading'}
            case 'まだ読んでいない' {$book->{state} = 'stack'}
            case 'いつか欲しい' {$book->{state} = 'wish'}
            else {}
        }
    }
    return \@list
}

1;

これでgetの返り値として,本のデータがハッシュとして入った配列の参照が 返ってきます.続いてこれを使って読書メーターに登録していきます. 「状態」に関しては使いやすい様に英語に直しています.

dokusyometer.pl

WWW::Mechanize を使ってソースを見ながらぽちぽち作成.やはり細かいことは ソースを見て下さいな.「すでに読んだ」だけは日付の指定ができるのでやっています.

use strict;
use warnings;
use WWW::Mechanize;
use DateTime::Format::HTTP;
use SSBCSV;

my $url = "http://book.akahoshitakuya.com";
my $user = 'your email';
my $pass = 'your password';
my %state_hash = (
    read => 1,
    reading => 2,
    stack => 3,
    wish => 4,
    );

my $mech = WWW::Mechanize->new();
$mech->get($url . "/login");

$mech->form_number(2);
$mech->submit_form(
    fields => {
        mail => $user,
        password => $pass,
    });

my $ssb = SSBCSV->new("stocks.csv");
my $res = $ssb->get;

foreach my $book(reverse @{$res}){
    $mech->get($url . "/b/" . $book->{isbn});
    $mech->follow_link(
        url_regex => qr{^/add¥.php},
        n => $state_hash{$book->{state}},
        );

    if($book->{state} eq 'read'){
        my $dt = DateTime::Format::HTTP->parse_datetime($book->{date});
        my $year = $dt->year;
        my $month = sprintf("%02d", $dt->month);
        my $day = sprintf("%02d", $dt->day);
        $mech->form_number(2);
        $mech->select('read_date_y', $year);
        $mech->select('read_date_m', $month);
        $mech->select('read_date_d', $day);
        $mech->submit;
    }
    sleep(1);
}

これを走らせたら終わりです.ログとか一切吐いてないですが,欲しい人は 自分で書いてやってください w

これからやること

当然ですが,読書メーター以外にも適応しやすいようにしていますので, いろいろ作っていきます.フローは同じで,WWW::Mechanize でログインして 登録する手段を解析して,できあがったら SSBCSV モジュールと組み合わせるだけ. 簡単ですね.

とりあえず現状の同期が終わったら,次は Plagger に移って行く予定です. 以上,取り急ぎ.