2007年9月アーカイブ

以前書いた Web::ScraperでCISCO RECORDSをスクレーピングという記事に対してBig Sky :: Web::Scraper 0.15で何が変わったのか...とおまけでWeb::Scraper 0.15での添削例として扱ってもらったので、さらにリプライ。

treeを壊さずやるとすれば、TextNodeを参照するのがいいかと思います。
例えば、XPathのnode()を使い、番号指定で取得します。だた現状のWeb::ScraperではTextNodeはショートカットで参照出来ませんので、以下のようにstring_valueを返すように手を加えると上手く行きます。
問題が一つ。 添削してくださったパッチだと
process '//li/node()[4]', 'title' => sub {$_->string_value;};
となっているのですが、4番目とは限らないんです。

たとえば、
http://www.cisco-records.co.jp/html/item/004/010/item393180.html
は何曲か試聴サンプルがないために、この処理だと取得できないです。

ただ
process '//p[@class="de_star"]/node()[2]', 'star' => sub {$_->string_value;};

こちらは例外がないのでばっちり動きます。
更にさっきアップされていた0.16では

0.16 Tue Sep 18 04:48:47 PDT 2007

- Support 'RAW' and 'TEXT' for TextNode object

ということなので

process '//p[@class="de_star"]/node()[2]', 'star' => 'TEXT';

でも、大丈夫でした。

あと、相対URLの展開ですが、今のところコールバック関数内では展開されないようです。
なので、添削していただいたものでは意図するように動かないようです。
ただ、こっちは深く追っていないので定かではありません。つっこみ歓迎です。

ともかく、フィードバックありがとうございました。
大変勉強になりました。

というわけで、妹の結婚式にハワイに行ってきました。

2007091701.jpg

2007091702.jpg

2007091703.jpg

式はどこかの家を借りてこじんまりとハワイアンスタイルでとり行われました。
目の前・・・というか庭の塀の先はすぐに海という、ものすごい綺麗なところでした。
うまく写真撮れなかったけど普通にウミガメがいたのがびっくりでした。

2007091704.jpg

2007091705.jpg

2007091706.jpg

新しい弟はRyan君。すごくナイスガイ。むちゃくちゃいいやつ。
日本語はほとんど話せないのに僕のつたない英語を一生懸命に聞いてコミュニケーションを取ってくれました。
年末にはこっちに遊びに来るらしいので、それまでに英語力を回復させてもっともっとしゃべれたらいいなぁと思います。

Ryanの弟のJohn君は今年の10月から北海道に留学する予定だけあって日本語が結構上手。
そのおかげで、おしゃべりなうちの母に捕まってたのがちょっと気の毒でした。

2007091707.jpg

2007091708.jpg

涙こそないものの笑いありフラダンス教室ありダンスありで、すごくアットホームな感じでいい式でした。

二人ともお幸せにね!

というわけで、2日前から妹の結婚式のためハワイに来てます。

2007091601.jpg

2007091602.jpg

詳細は帰国してからアップするけど、とりあえず日焼けっちゅーか火傷痛いっ ><

いまさらWeb::Scraperを使ってみました。
使うネタがなかったのがスルーし続けた一番の理由だったのですが、それではいけないと思い、CISCO RECORDSの商品情報を取得するスクリプトという、僕以外誰も興味がないスクリプトを書いてみました。

cisco_scraper.pl
#!/usr/bin/perl

use strict;
use warnings;

use Web::Scraper;
use URI;
use YAML;
use Data::Dumper;

my $uri = shift;

my %scraper;

$scraper{'link'} = scraper {
    process 'a', 'name' => 'TEXT';
    process 'a', 'uri'  => sub {
        return URI->new_abs( $_->attr('href'), $uri )->as_string;
    };
    result qw/name uri/;
};

$scraper{'genre'} = scraper {
    process '//a[1]', 'top'   => $scraper{link};
    process '//a[2]', 'style' => $scraper{link};
    result qw/top style/;
};

$scraper{'track'} = scraper {
    process 'li', 'title' => sub {
        my $elem = shift;
        $elem->find_by_tag_name('span')->delete;
        return $elem->as_text;
    };
    process 'li>a', 'uri' => sub {
        return URI->new_abs( $_->attr('href'), $uri )->as_string;
    };
    result qw/title uri/;
};

$scraper{'item'} = scraper {
    process 'td.de_title',      'title'  => 'TEXT';
    process 'td.de_artist',     'artist' => 'TEXT';
    process 'td.nm_jacket>img', 'image'  => sub {
        return URI->new_abs( $_->attr('src'), $uri )->as_string;
    };
    process 'td.de_price',              'price'   => 'TEXT';
    process 'td.de_label>a',            'label'   => $scraper{link};
    process 'td.de_genre',              'genre'   => $scraper{genre};
    process 'td[headers="de_format"]',  'format'  => 'TEXT';
    process 'td[headers="de_release"]', 'release' => 'TEXT';
    process 'td[headers="de_country"]', 'country' => 'TEXT';
    process 'td[headers="de_sheet"]',   'sheet'   => 'TEXT';
    process 'td[headers="de_arrival"]', 'arrival' => 'TEXT';
    process 'td[headers="de_nomber"]',  'number'  => 'TEXT';
    process 'p.de_star',                'star'    => sub {
        my $elem = shift;
        $elem->find_by_tag_name('span')->delete;
        return $elem->as_text;

    };
    process 'ul[id="de_sound"]>li', 'tracks[]' => $scraper{track};
    result
        qw/title artist image price label genre format release release country sheet arrival number star tracks/;
};

my $item = $scraper{'item'}->scrape( URI->new($uri) );
warn Dump $item;

で、ためしに、このページを解析してみると

$ ./cisco_scraper.pl http://www.cisco-records.co.jp/html/item/003/100/item355640.html
---
arrival: 2007/09/03
artist: Capsule
country: JAPAN
format: 12"EP
genre:
  style:
    name: POP DANCE
    uri: http://www.cisco-records.co.jp/list/style.php?qGenre=4&qStyle=128
  top:
    name: HOUSE
    uri: http://www.cisco-records.co.jp/html/genretop/genretop_4.html
image: http://www.cisco-records.co.jp/upimages/003/100/item355640p1.jpg
label:
  name: Contemode
  uri: http://www.cisco-records.co.jp/html/label/L348/labelL34869_0desc.html
number: 95449
price: '¥1,365'
release: 2007/09/05
sheet: 1
star: ★★★★★
title: Capsule Rmx EP
tracks:
  - title: ' Sugarless Girl (Rmx Ver.) '
    uri: http://www.cisco-records.co.jp/track/003/100/95449_1.ram
  - title: ' CrazEEE Skyhopper (Rmx Ver.) '
    uri: http://www.cisco-records.co.jp/track/003/100/95449_2.ram

こんな感じになります。
後はブックマークレットとか作れば今よりもっと簡単にレコードレビューが書けるはず。

Web::Scraper自体はとっても簡単だし、コールバックのおかげでとっても柔軟です。
・・・が、DSLというかXPathがいかんせんめんどっちー。
たとえば

<li><span>1</span>Track 1</li>

というHTMLから"Track1"だけを抽出しようにも

process 'li', 'title' => 'TEXT';

だと

1Track1

なんて結果になるのでそれを回避するために

process 'li', 'title' => sub {
    my $elem = shift;
    $elem->find_by_tag_name('span')->delete;
    return $elem->as_text;
};

なんてことをしてるのですが、もっといい方法があるはず。
この辺のレシピがもっともっとあったら幸せになれそうです。

追記(09/19/2007):

Big Sky :: Web::Scraper 0.15で何が変わったのか...とおまけ

string_valueを使えばスマートになるそうです。thx!
ついでに0.15からはURI->new_absしなくて@hrefで絶対URLを取得できるそうな。便利。

追記(09/19/2007):

さらにリプライ

参考:

typesterさんが言い出しYappoさんが提供しているcodereposはcommit権を得れば、公開されているコードを誰でもいじくれるステキプロジェクトです。
こういうフルオープン全開な試みはときめきます。
ときめいているだけではダメなので、早速お願いしてcommit権を頂きました。

で、せっかくなので何か提供しようと思ったので、行き場に困っていたけど常々使っているDBIx::Class::InflateColumn::DateTime::Autoをとりあえずあげてみました。

じゃんじゃんばりばり添削していただきたいと思います。

で、みんなもっともっとソースを晒せばいいんだと思います。

追記:

プロフィール

このアーカイブについて

このページには、2007年9月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2007年8月です。

次のアーカイブは2007年10月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。