2011年 12月 07日

microdata を適当に抜き出す Perl スクリプト

あんまり仕様書読みこめてないけど書くだけ書いてみた。CPAN にあるのは依存がひどいし、別に HTML::Parser 的なもの一個の依存で JSON 返すようなのでいいじゃんと思った。やる気があればテスト書いて CPAN にあげたりしたいけど、あんまりやる気わかない。

結局 HTML::Parser ではなく HTML::TreeBuilder::LibXML にしたけど、普通に入るモジュールなのでよさそう。

レポジトリをつくってテストを書いた。
https://github.com/cho45/HTML-Microdata/blob/master/lib/HTML/Microdata.pm

use v5.12;
use LWP::Simple qw($ua);
use URI;
use JSON::XS;

my $uri = URI->new('http://www.lowreal.net/');

my $res = $ua->get($uri);
my $microdata = HTML::Microdata->parse($res->content);

say encode_json $microdata->items->{cho45}->{properties};

package HTML::Microdata;

use HTML::TreeBuilder::LibXML;
use Scalar::Util qw(refaddr);
use Hash::MultiValue;

sub new {
	my ($class, $args) = @_;
	bless {
		items => {},
	}, $class;
}

sub parse {
	my ($class, $content, $opts) = @_;
	my $self = $class->new($opts);
	$self->_parse($content);
	$self
}

sub items {
	my ($self) = @_;
	$self->{items};
}

sub _parse {
	my ($self, $content) = @_;

	my $tree = HTML::TreeBuilder::LibXML->new_from_content($content);
	my $scopes = $tree->findnodes('//*[@itemscope]');
	my $number = 0;
	for my $scope (@$scopes) {
		my $type = $scope->attr('itemtype');
		my $id   = $scope->attr('itemid');

		unless ($scope->id) {
			$scope->id($number++);
		}

		if (my $refs = $scope->attr('itemref')) {
			my $ids = [ split /\s+/, $refs ];
			for my $id (@$ids) {
				my $props = $tree->findnodes('//*[\@id="' . $id . '"]//*[\@itemprop]');
				for my $prop (@$props) {
					my $name = $prop->attr('itemprop');
					my $value = $self->extract_value($prop);
					$self->{items}->{ $scope->id }->add($name => $value);
				}
			}
		}

		$self->{items}->{ $scope->id } = {
			($id ? (id => $id) : ()),
			type       => $type,
			properties => Hash::MultiValue->new,
		};
	}

	my $props = $tree->findnodes('//*[@itemprop]');
	for my $prop (@$props) {
		my $name = $prop->attr('itemprop');
		my $value = $self->extract_value($prop);

		my $scope = $prop->findnodes('./ancestor::*[@itemscope]')->[-1];

		$self->{items}->{ $scope->id }->{properties}->add($name => $value);
	}

	for my $key (keys %{ $self->{items} }) {
		my $item = $self->{items}->{$key};
		$item->{properties} = $item->{properties}->multi;
	}
}

sub extract_value {
	my ($self, $prop) = @_;

	my $value;
	if (defined $prop->attr('itemscope')) {
		$value = $self->{items}->{ $prop->id };
	} elsif ($prop->tag eq 'meta') {
		$value = $prop->attr('content');
	} elsif ($prop->tag =~ m{^audio|embed|iframe|img|source|video$}) {
		$value = $prop->attr('src');
	} elsif ($prop->tag =~ m{^a|area|link$}) {
		$value = $prop->attr('href');
	} elsif ($prop->tag eq 'object') {
		$value = $prop->attr('data');
	} elsif ($prop->tag eq 'time' && $prop->attr('datetime')) {
		$value = $prop->attr('datetime');
	} else {
		$value = $prop->findvalue('normalize-space(.)');
	}

	$value;
}
2011年 12月 05日

[tech] カテゴリは長くなりがちなので、最初の一段落を残して残りは「続きを読む」みたいにしたいかもしれない。微妙に面倒くさい。

hAtom をやめて microdata にしてみた。

2011年 12月 04日

Googleプロフィールにウェブサイトを関連付ける

500 Can't connect to hail2u.net:443 を見て、そんなことできたのかと思いやってみたら見事にハマった。

やりたかったことは以下の通り

で、まず http://lowreal.net/ 以下のページで

<link rel="author" href="http://www.lowreal.net/"/>

をつけた。これで Structured Data Testing Tool  |  Google Developers を確認すると、linked author profile = http://www.lowreal.net/ になる。この時点ではまだ Google プロフィールとは関連づいていないので、Error: Author profile page does not have a rel=me link to a Google Profile とでた。

ついで、http://www.lowreal.net/

<a rel="me" href="https://plus.google.com/114431815111528304586">Google+</a>

を追加してみたが、これがうまく行かず。profiles.google.com じゃないといけないのか? とかいろいろやってみたけれど、変化がなく、Error: Author profile page does not have a rel=me link to a Google Profile が出続けた。

諦めようかなーと思いはじめたが、なんとなく vcard あたりの解釈と衝突している気がしたので、フッタにリンクを移したら、めでたく Verified: Authorship markup is correct for this page になった。よかったよかった。

http://www.google.com/webmasters/tools/richsnippets?url=lowreal.net 見るとメタデータたくさんあって気持ちいいですね。

フォトライフ記法

写真を貼るときにはてなフォトライフの記法を使って貼っているが、せっかくなので microdata で Photograph として認識されるように展開フォーマットを変えた。Google が解釈するようになるといいなー

<span itemscope itemtype="http://schema.org/Photograph">
  <a href="/2011/12/03/1" class="hatena-fotolife" itemprop="url">
    <img src="http://cdn-ak.f.st-hatena.com/images/fotolife/c/cho45/20111127/20111127131949.jpg" alt="photo" class="hatena-fotolife" itemprop="image">
  </a>
</span>

こんな感じにしてある。author については url の先に rel="author" があるので勝手に認識してほしい。

[tech] カテゴリと [photo] カテゴリと、asin が含まれるエントリだけフィードに出すようにした。

2005年 10月 30日

Canon EXPO 2005 in Tokyo

昨日行ってきた@品川・新高輪プリンス。前回 (2000) より全然人が多かった。特に内定者がいっぱい……

そんなにおもいっきり面白い展示があったわけじゃない気がする。SED ぐらいかなぁ。SED は確かに綺麗だった。綺麗だったけど庶民には関係なさそうで略。EOS-5D を持ってみたけど重かった……そして全然関係ないところ (AF フレームがファインダーに映るとか) に感動してた。どれにでもついてるよボケ。Wireless IXY は意味があるのか疑問だったんだけど、実際見てみてやっぱり疑問だった。デジタル一眼が Wireless でコンピュータに直接転送できたら便利かもしれないけど、アマチュアには関係ない話だなぁとかなんとか。

ってことで面白さとしては携帯プロジェクタがなんかやけにかっこよくてよかった。チラついてたけど。

ソフトウェア関連で Microsoft と云々が……Canon のカラーマネージメントソフトウェアが Windows Vista に搭載されるとか、ぶっちゃけどうでもいいのでよく見てこなかったけど……

なんかあとは自動システムが多かったなぁ。顔識別・笑顔識別・オート追尾とか。

デジタル一眼欲しい。

印刷データ管理とかいってるけど、印刷しなくてすむようなシステムになるべきとか言ってたらキヤノンはプリンタ作ってんダカラ!とか怒られた (誰に)。わろす。

詳細 @Impress Watch