MovableType アーカイブ
MovableTypeの使いこなし、カスタマイズ、機能拡張など、blogツールの機能についての話題です。いろいろプログラムも書いていきます。

2007.03.15 (木)

Firefox でブログ投稿に必須の It's All Text!

Webページのテキスト入力エリアでblogなど長文を入力するのは非常に苦痛です。普段使っているエディタを使いたくなるものです。DonutなどIE系ブラウザを使っていた頃は AreaEditor というソフトを使っていました。フォームのテキスト入力エリアを任意のエディタで編集できるというソフトでたいへん便利でした。Firefoxを使うようになって同様のソフトを探したところ、mozex というプラグインが見つかり、それを使っていました。

mozex にはいくつか不便な点があり、我慢して使っていたのですが、もっとよいソフトが登場しました。

窓の杜 - 【NEWS】「Firefox」のテキスト入力フォームを外部エディターで編集「It's All Text!」

「It's All Text!」は、Webページ上に設置されたテキスト入力フォームを好みのテキストエディターで編集可能にする「Firefox」用の拡張機能。普段使い慣れたテキストエディターで検索・置換機能などを活用すれば、ブログやWikiページで長くなりそうな文章を効率よく編集できるだろう。
It's All Text

「It's All Text!」を早速使ってみたところ非常に快適です。上の図右下のボタンでエディタを呼び出すことができます。これでもうmozexは要りません。具体的には下記のような点でmozexより便利になりました。

  • ボタンクリックでエディタを起動できる。mozexは右クリックメニューから2階層目の項目を選ばなければならないので面倒。
  • エディタ編集中にWebブラウザを操作できる。mozexはエディタ編集中はWebブラウザに切り替えるとエラーダイアログが出て操作できない。
  • mozexではエディタ終了後にファイルが消せない旨のエラーダイアログが出ることがあった。It's All Text!では起きない。
  • mozexでは時々Firefoxが落ちることがあった。It's All Text!では今のところ起きない。

インストールも簡単だし、エディタの選択以外に特に設定も必要ないし、実によくできてます。もはや It's All Text! 無しではblog記事も書けません。blogだけでなくあらゆるWebのフォームの入力に欠かせないものになっています。

[BCY:10.9km]
コメント <1> Posted by tama | 2007.03.23

テキストエリアが空の状態からエディタで入力すると文字化けしますね。フォーム上で少しだけ文字を入れてからエディタで編集すれば大丈夫なようです。

2006.04.18 (火)

はてなダイアリーを緊急避難所に

はてなダイアリーは他のブログサービスからの引越しだけでなく、他のブログサービスへ出て行く方もしっかりサポートしてるんですね。

はてなダイアリー、日記のエクスポート機能にMovable Type形式を追加 - Internet Watch -

はてなは、ブログサービス「はてなダイアリー」のエクスポート機能にMovable Type形式を追加した。

出て行く方もサポートするのは太っ腹ですが、万が一の時には転出も可能という安心感から転入して来る人が却って増えるのかもしれません。書き綴った文章は書いた本人のものですから、囲い込んだりせずに柔軟に活用できるようにしてくれる姿勢にとても好感が持てます。

自分のblogサイトに障害が起きた時や、バージョンアップなどで一時的に止める時などに、はてなダイアリーを緊急避難所として使うこともできそうです。自blog再開時に、はてなダイアリーで更新した日の分も反映できるのがよいですね。そんな使い方ははてなさんに失礼で迷惑ですかね。でもはてなダイアリーから離れられなくなっちゃうかもしれないことを考えると、はてなさんにとっても悪い使い方じゃないと思います。

2006.02.27 (月)

DreamweaverでMovableTypeテンプレートの編集ができるのか

MovableTypeのテンプレートの編集は大変だと思ってましたけど、Dreamweaverで編集する拡張機能が以前から提供されてたんですね。それも無償だったとは。

Dreamweaver 8の拡張機能、Movable Type 3.2のテンプレートを作成可能に - Internet Watch -

Dreamweaver 8は、Webサイト構築やWebアプリケーション開発を行なうプロフェッショナルユーザー向けツール。この拡張機能を利用すると、Dreamweaver上からMovable Typeのタグの挿入や編集が可能になり、Movable Typeのテンプレートをカスタマイズできる。また、タグや属性の説明も参照できるようになっている。

もしDreamweaverを持っていたら MovableType を 3.X にバージョンアップする動機になってたかもしれません。これまでテンプレートはテキストエディタで編集して、MTに登録し、わざわざページのリビルドをかけて結果の確認を行ってました。むちゃくちゃ時間がかかるのであまりいじりたくありません。なんだかバカなやり方なのでもっとよい方法があると思ってました。そういう方法もあったのか。

MTのpluginで拡張したタグも対応してくれるんですかね。さすがにそれは無理か。PERLのインタープリタを内蔵しないと拡張タグの情報を取得することはできないでしょうしね。

DREAMWEAVER 8 Commercial



マクロメディア (2005/10/12)
¥ 43,880
ASIN: B000BDKU9M
sixapart
[BCY:12.60km]

2006.02.26 (日)

AmazonのURLのバリエーションはいくつある?

Amazonリンク生成スクリプトの記事で作ったCGIとブックマークレットをいつも使っているのですが、Amazonのウィッシュリストから開いた商品ページではブックマークレットがうまく動かないことに気づきました。URLの形式が普通に商品ページにたどりついた時と異なっているんですね。

とりあえず対処療法的にブックマークレットを修正しました。アドホックな対応ですが、もともとAmazonのURLの書式が明文化されてるわけでも不変性が保証されてるわけでもないので、将来の修正は覚悟の上で簡単なやり方で動かしておけばよいでしょう。ブックマークレットのスクリプトはこうなります。

javascript:var%20id='tama0e-22';var%20u=document.location.href;var%20i;var%20asin;if((i=u.indexOf('ASIN'))>=0){asin=u.substring(i+5,i+15);}else%20if((i=u.indexOf('detail/-/'))>=0){asin=u.substring(i+9,i+19);}void(window.open('http://blog.bibinko.com/cgi-bin/amazon-isbn.cgi?asin='+asin+'&t='+id))

この Amazonリンク作成"リンクをリンクバーにでも持っていけば簡単に呼び出せます。

2006.01.04 (水)

コメントSPAMにアップアップ

load

このところ毎日のようにコメントSPAMの嵐がやってきます。対策を講じてあるので実際にSPAMメッセージが書き込まれてしまうことはあまりありません。しかし、連続して大量に書き込もうとしてくるので、サーバーの負荷が一時的に急上昇して大迷惑を被っています。上のグラフはシステム負荷(ロードアベレージ)をプロットしたものですが、一日に一度は必ず大きく上昇してます。ロードアベレージが10を超えて20近くまで達しており、完全に処理能力限界を超えてます。我が家のサーバーはたいへん非力なマシンでメモリもわずかしか搭載してません。これだけの負荷がかかるとメモリが足りなくなってほぼ無反応に近い状態になってしまいます。グラフが一部途切れているのは、負荷を記録するプロセスさえ動かなくなるからです。

各種対策によってコメントSPAMが書き込まれるのは防止できますが、こうして負荷が増大してしまうことは避けられません。なんとかよい方法はないものでしょうか。

2005.12.24 (土)

コメントSPAM大量襲来

このサイトにもいくつかのコメントSPAM対策を施してあったので、それをすり抜けてくるものはたいした数はありませんでした。ところが、今日は大量にやってきました。一気に80件ほどが書き込まれてしまいました。こりゃたまらんということで新たな対策をします。

トラックバックSPAM対策のために以前導入した方法を、コメントSPAMでも導入することにしました。 mt-spamstopはpluginsフォルダに入れるだけなので非常に簡単です。GNUE(鵺) さんどうもありがとうございます。これで今回のような大量書き込みからは逃れられるかな。

今回のSPAMコメントは80件ありましたが、ソースIPアドレスは29種類しかありませんでした。禁止IPへの登録でもどうにかなるかもしれませんが、敵さんもアノニマスProxyをどんどん切り替えて使うなどしてるでしょうし、他の業者もわんさといるでしょうからすぐに追いつかなくなるでしょうね。大量のSPAMコメントの削除も面倒でした。1つ1つ消してはいられないので、データベースを直接参照して削除し、再構築することで一気に消せました。

2005.12.20 (火)

blog記事にタグを付けよう

flickrやはてなブックマークなどに見られるように、写真やブックマークなどのアイテムをカテゴリで分類するのではなくタグでラベリングする動きが急速に進んでいます。固定されたカテゴリ階層ではなく、集合知としてダイナミック発展・収束していくタグ集合の方が自由度や柔軟性が高く、関連付けや検索に適しているということでしょう。

テクノラティ、タグやカテゴリーでブログを検索できる「タグ検索」 - Internet Watch -

テクノラティジャパンは、ブログ検索サービス「Technorati.jp」の新サービスとして、「タグ検索サービス」を12月20日から開始した。ブログの記事に付与されたタグやカテゴリー属性を対象としてブログを検索できる。
(略)
現在のところ、検索の対象となっているのはブログのカテゴリーが中心だが、HTMLが利用できるブログであれば、「rel="tag"」のHTMLタグを記事内に記述することで任意のタグを設定でき、テクノラティではタグを付与するための説明ページも用意している。

当然ながらblogの記事にもタグを付けようという動きになっていきます。MovableTypeでも記事にカテゴリをつけることはできますが、記事に複数のカテゴリを付けるのは結構面倒ですし、たくさん付けることは想定されていないと思われます。カテゴリの種類を大量に増やすと使い勝手が悪くなるでしょう。

カテゴリではなく、タグを記事に付ける方法としてテクノラティでは下記の方法を示しています。

<a href="タグ名に関するお好きなURL" rel="tag">タグ名</a>

そして、URLとしてテクノラティのタグ検索のURLを示してくれています。例えば、「タグ」というタグを付けるには、次のような記述を記事中に埋め込むことになります。

<a href="http://technorati.jp/search/search.html?queryMode=tag&queryTag=%e3%82%bf%e3%82%b0&language=ja" rel="tag">タグ</a>

この記述法は広まるでしょうか。どこのblogでもこの方式でタグを埋め込むようになると、タグの有用性が格段に上がると思います。

この記述法は簡単ではありますが、記事を書くたびにこれを書くのは面倒です。なんとかツールの側で対応してもらいたいものだと思います。 とりあえずCGIを作ってこの記述を簡単に書けるようにしてみました。こんなコードになります。

#!/usr/bin/perl

use strict;
use CGI;

# get cgi parameter
my $cgi = new CGI;
my $tag = $cgi->param("tag");
my $tagenc = $tag;
$tagenc =~ s/([^\w ])/'%' . unpack('H2', $1)/eg;

print << "EOF";
Content-type: text/html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title> Generated Tag </title>
<body>

<a href="http://technorati.jp/search/search.html?queryMode=tag&queryTag=$tag&language=ja" rel="tag">$tag</a>
<br />
<a href="http://technorati.jp/search/search.html?queryMode=tag&queryTag=$tagenc&language=ja" rel="tag">$tag</a>

</body>
</html>
EOF

exit;

これを次のようなHTMLから呼び出します。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Generate Tag</title>
</head>

<body>
<h1>Generate Tag </h1>
<form action="cgi-bin/tagurl.cgi" method="GET" name="tagurl">
  TAG:
  <input type="text" name="tag" value=""/>
  <input value="search" type="submit"/>
</form>

</body>
</html>

すると上記のようなタグ記述が出力されます。これをコピー&ペーストしてblog記事に埋め込めばよいわけです。非常に原始的なツールですが、タグ記述生成ツールとしてここに置いてしばらく使ってみようと思います。

[] [] [] []

2005.12.07 (水)

track word で検索キーワードを分析

Webalizerでアクセス分析をしているので、このblogにどんな検索キーワードでやってくるのかはだいたい把握できているつもりです。でもWebalizerの表示は月ごとの検索回数ランキング程度で、細かいところまでの分析はできません。そう思っていたところに、検索キーワードの分析を行ってくれるサービスが始まりました。track wordというサービスです。

ブロガーの皆様へ - トラックワード

トラックワードをブログに設置すると、あなたのブログの検索キーワードを詳細に分析することができます。 また、ブログには、そのページが「どんなキーワードで」検索されているかが表示されるようになります。

Webalizerではできなかった日ごとのキーワードやその増減、新キーワードの出現、どのページに飛んできてるのか、といったあたりの分析ができるかもしれないと思って早速貼り付けてみました。各ページの一番下のほうに表示されていると思います。各ページにどんなキーワードで飛んで来ているのかがわかっちゃいます。

登録ユーザーは日ごとの非常に詳細なレポートを見ることができます。たった一日の間にこんなにも多くの種類の検索語でここにたどりついているのかとびっくりします。RSSでも配信されるので、毎日開いてみるのが楽しみです。

[BCY:13.15km]

2005.11.15 (火)

Google Analytics でアクセス解析開始

このサイトではWebalizerを使ってアクセス解析をやってます。たいした規模ではないので解析するほどではないのですが、それでもいろいろな傾向がわかって楽しめます。 trackfeedというサービスを使ってリンクの解析もやってます。サイトにやってくるルートがわかってとても便利です。

Googleが新サービスとしてWeb解析サービスを始めました。Google Analyticsというそうです。

グーグル、Web解析サービス「Google Analytics」を無償提供 - Internet Watch -

Google Analyticsでは、Webサイトへの訪問経路や、クリックされた回数と実際に購入された数の比率である「コンバージョンレート」、サイト上におけるユーザーの行動などを分析するサービス。これにより、効率的なメールキャンペーンの特定や、サイト設計の最適化など、オンラインマーケティングのさまざまな面を向上できるとしている。
Google Analytics

さっそくこのサイトにも導入してみました。Google Analytics の利用登録をして、Webページに指定のスクリプトを挿入するだけです。MovableType なら各種テンプレートに挿入してリビルドですね。結果が出るにはしばらく時間がかかるようです。どんな解析をしてくれるのか楽しみです。

2005.09.06 (火)

TypePadでもAmazonウィッシュリストを表示できる

日本の大手blogサービスにはTypePadで運営しているところがいくつかありますが、大幅に機能アップが行われたようです。

携帯電話向け機能を拡充、Podcastingに対応した「TypePad 1.6日本語版」 - Internet Watch -

これまでTypePadでは、サイドバーにフォトアルバムの画像を表示することが可能だったが、今回は新たに指定した画像のみを表示する機能が追加された。また、サイドバーでHTMLを利用する機能はこれまでHack的に利用できていたが、1.6では正式に「メモ」機能としてサイドバー表示が可能になった。このほかサイドバー用のモジュールも追加され、インスタントメッセンジャーのオンライン状態通知機能、Amazon.co.jpのウィッシュリスト表示機能が追加された。

最後のAmazonのウィッシュリスト表示機能に注目です。我がタマゴログでは、1年以上前からAmazonのウィッシュリストをサイドバーに表示してきました。平田さん作成のプラグインを若干改造して実現しています。同じことが大手サービスでもできるようになったんですね。blogにウィッシュリストを載せておくととっても便利なので、多くの人が使うようになるのが楽しみです。

ところでAmazonのAPIドキュメント通りに作ると10個までしかウィッシュリストは取得できないんですが、そのへんはどうなっているのかな。

2005.02.20 (日)

Trackback spam の予防

ここにもコメントSPAMはかなりしつこくやってきます。一日に百個弱といったところでしょうか。だんだん増えてきますね。幸い対策をしてあったので、すり抜けてくる数件を手で削除するくらいで済んでます。

ここ数週はいよいよトラックバックSPAMも始まったようです。まだ日に数件ですが、面倒なことにならないように対策をしておくことにしました。いろいろと方法はあるようですが、あまり手間はかけたくないので下記の方法を使わせていただきました。

鵺的:想空間: mt-spamstop-tb_20050213

概  要: <A>タグを含むトラックバックスパムをブロック
利用方法: Plugins フォルダに入れるだけ

プラグインを放り込むだけっていう簡便さがいいです。鵺的:想空間さん、ありがとうございます。これでしばらく様子をみてみます。


[追記]

上記対策をしたとたんにいくつも連続でトラックバックSPAMが来るようになりました:( 残念ながら本文には<A>タグは入ってなくて、タイトルとブログ名には何やら入っているので、上記対策だとブロックしきれません。しかたがないので下記コードを追加しました。SPAMチェックっていうコメント行のすぐ下に同様の行が並んでるところに追加します。 なるべくならこの安易な判別法は使いたくなかったのですが、手っ取り早くすませるために目をつぶりました。もうちょっとましな判別法はないですかね。

  $err .= "excerpt text have no japanese char. " if $excerpt !~ m/[\x80-\xff]/;

鵺的:想空間さんの方法はMT本体にパッチを当てたりしなくてすむので助かります。ログが残るのもいいですね。効果が一目瞭然で確認できます。感謝と報告を兼ねてトラックバックしておきます。

2005.01.28 (金)

Movable Typeの脆弱性対策

書くのを忘れてましたが、このサイトもMovableTypeで運用してますから、26日時点で対応しておきました。

Six Apart Japan||シックス・アパート

2005年01月25日 【重要】 Movable Typeの脆弱性と対策へのお願い 本日、Movable Typeの脆弱性により、スパムメールの送信を幇助してしまう現象が発生することが分かりました。

ダウンロードしたファイルを展開して、pluginsディレクトリに置くだけなので簡単した。もしパッチ当てだったりしたら、若干改造を加えているだけに面倒なことになりそうだったので助かりました。スパムメールの発信元になんかなりたくないですよね。

ここ数日すごい勢いでコメントスパムが来てます。ほとんどは以前書いた対策でブロックされてます。すり抜けてくるのは多くても一日数件程度ですんでます。対策しておいてほんとよかった。 noblog短気な猫3rdさんの方法がもっと広まるとよいかとも思いますが、皆がこの対策法を取るといずれ破られちゃいますね。なるべく破られないことを祈ります。

2005.01.09 (日)

写真のカレンダー表示プラグイン MTPhotoCalendar の作り方

昨日紹介した写真のカレンダー表示を行うMTPhotoCalendarの作り方を紹介します。やぼったいプログラムになってしまってますので、どなたかもっといいコードで書き直して頂けると幸いです。

MovableTypeのプラグインのプログラムは、MTをインストールしたディレクトリの下のpluginsに置いておけば自動的に読み込まれて実行されます。ここでは mt-photo-calendar.plという名前でプラグインプログラムのファイルを作成し、pluginsディレクトリに置いています。 実行されるプログラムでは、次のように書いておくとテンプレートで使用するタグを増やすことができます。下の例では、MTIfCalendarImage、MTCalendarImageSrc、MTCalendarImageWidth、MTCalendarImageHeightという4種類のタグを追加しています。

use MT::Template::Context;

# MTCalendarImageタグを登録
MT::Template::Context->add_conditional_tag("IfCalendarImage" => \&ifcalendarImage );
MT::Template::Context->add_tag("CalendarImageSrc" => \&calendarImageSrc );
MT::Template::Context->add_tag("CalendarImageWidth" => \&calendarImageWidth );
MT::Template::Context->add_tag("CalendarImageHeight" => \&calendarImageHeight );

MTのテンプレートでは4つのタイプのタグを定義することができます。

  • 変数タグ
  • コンテナタグ
  • 条件タグ
  • グローバルフィルタ

それぞれ、プラグインの中から下記の呼び出しを行うことで追加することができます。

  • MT::Template::Context->add_tag($name, \&subroutine);
  • MT::Template::Context->add_container_tag($name, \&subroutine);
  • MT::Template::Context->add_conditional_tag($name, \&subroutine);
  • MT::Template::Context->add_global_filter($name, \&subroutine);

条件タグでは、サブルーチンの返す値が真であればタグに囲まれた部分の有効になりますが、偽であればタグに囲まれた部分が無効になります。変数タグはサブルーチンの返す値にそのまま置き換えられます。 このあたりの詳しいことは、 MovableType プログラミングインターフェイスで解説されています。 また、シェルのコマンドラインで下記のコマンドを実行すれば解説を読むことができます。これらを読めばプラグインの作り方の大体のところはわかると思います。その他のクラスについても出てくるごとにperldocで読んでみるとよいでしょう。

% cd MTをインストールしたディレクトリ/lib
% perldoc MT::Template::Context 

上記のコードでは、条件タグを1つと、変数タグを3つ定義しています。各呼び出しの第一引数がタグの名前で、「MT」を除いた文字列を渡します。第二引数にタグを処理するサブルーチンへの参照を渡します。 最初の条件タグであるMTIfCalendarImageを処理するサブルーチンifcalendarImageは次のようになっています。

sub ifcalendarImage {
    my ($ctx, $arg) = @_;

    # 当該日のエントリーリストを取り出す
    my $entries = $ctx->stash('entries');

    # 時間の逆順にソートする
    sort { $a->created_on < $b->created_on; } @$entries;

    # SiteのURLを取得しておく
    my $blog = $ctx->stash('blog');
    my $site_path = $blog->site_path;

    # 画像取得準備
    my $src = "";
    my $maxwidth  = $arg->{width};
    my $maxheight = $arg->{height};
    my ($width, $height) = ($maxwidth, $maxheight);

    # 当日のimgタグを持つ最後のエントリを探す
    for (my $i = $#{$entries}; $i>=0; $i--) {

        # 本文を取り出す
        my $entry = $entries->[$i];
        my $text  = $entry->text;
        $text .= $entry->text_more if($entry->text_more);

        # imgタグを取り出す
        while ($text =~ m|<img (.*?)>|sigc) {
            # src属性を取り出す
            my $img = $1;
            if ($img =~ m|src\s*?=\s*?"(.*?)"|si) {
                # 画像urlを取得できた場合
                $src = $1;

                # ImageMagickの準備
                my $image = Image::Magick->new;

                if (substr($src, 0, 4) cmp "http") {
                    # ローカルの画像ファイルをロードする
                    my $filename = $site_path . $src;
                    $image->Read($filename);
                } else {
                    # リモートサイトから画像ファイルをダウンロードする
                    my ($imagedata, $retry);
                    for ($retry=3; $retry>0; $retry--) {
                        $imagedata = get($src);
                        last if ($imagedata);
                    }
                    if ($retry<=0) {
                        # ロード失敗
                        $src = "";
                        last;
                    }
                    $image->BlobToImage($imagedata) if ($imagedata);
                }

                # 画像サイズを取得
                ($width, $height) = $image->Get('width', 'height');
                if ($width == 0 || $height == 0) {
                    # 画像を取得できていない?
                    next;
                }

                # 指定サイズの収まらない場合はサイズ指定を調整する
                if ($width > $maxwidth || $height > $maxheight) {
                    my $wratio = $maxwidth  / $width;
                    my $hratio = $maxheight / $height;
                    if ($wratio < $hratio) {
                        $width  = int($width * $wratio);
                        $height = int($height* $wratio);
                    } else {
                        $width  = int($width * $hratio);
                        $height = int($height* $hratio);
                    }
                }

                # 画像が見つかったので終了
                last;
            }
        }
        last if ($src cmp "");
    }

    return 0 unless ($src cmp "");

    $ctx->stash('calendarImageSrc', $src);
    $ctx->stash('calendarImageWidth',  $width);
    $ctx->stash('calendarImageHeight', $height);

    return 1;
}

サブルーチンには2つの引数が渡されます。1つはコンテクストオブジェクト(MT::Template::Context)で、2つ目はタグの属性値を格納したハッシュへの参照です。 コンテクストオブジェクトからは、タグが呼ばれた時点でのページ作成中の中間状態を得ることができます。ここではコンテクストオブジェクトを$ctxという変数で受けています。$ctx->stash('状態名')で各種状態を取り出すことができます。この状態を引き出す名前についてはドキュメントが見当たらないので、MTのソースを探るしかなさそうです。ソースを眺めていると、次のことがわかりました。 MTCalendarタグの内側であれば、カレンダーの各日付を処理しながら順に何度も呼び出されることになるわけですが、呼び出された日付に属するエントリのリストを「entries」という名前で取り出すことができます。

プログラムの残りの部分では、エントリリストから個々のエントリのエントリオブジェクト(MT::Entry)を取り出して、記事の作成時刻や本文を処理しています。本文からimgタグを探し、画像ファイルのURLを取り出しています。

このプログラムでは、各日付の最後に書かれたエントリの最初の画像ファイルを取り出すようになっています。この規則もタグのパラメータにして選択できるようにするとよいでしょうね。

カレンダーの日付の各マスに画像を収めるために、画像サイズがマスのサイズを上回る場合は縦横比を保ったままちょうど収まるように縮小します。各日付のマスのサイズはMTIfCalendarImageタグの属性値として指定するようにしています。ここで指定された値は、サブルーチンの第二引数から取り出すことができます。ここでは$argという変数で受け取っており、$arg->{width}のように取り出します。 そして、実際のファイルから画像サイズを取り出して、縮小後のサイズを計算しています。

画像のサイズの調整に関しては、ここで計算するのではなく JavaScript でページロード時に計算する方法もあります。これもやってみたのですが、うまくサイズ設定が動かないことがあり断念しました。なにかよい方法があれば教えてください。

条件タグでは画像ファイルのURLや画像サイズは使わないので、これをコンテクストオブジェクトに保管しておきます。$ctx->stash('名前', 値)を呼び出すと任意の名前に状態を保管しておくことができます。stashを辞書で引くと「隠し場所」っていう意味なんですね。なるほど。

stashに隠した状態の値、すなわちコンテクストは、後で別なタグの処理の際に取り出すことができます。それが、画像URLと画像のサイズを取り出すタグの処理プログラムである下記のサブルーチンです。ここではstashから値を取り出して、戻り値として返しているだけです。

sub calendarImageSrc {
    my $ctx = shift;
    return $ctx->stash('calendarImageSrc');
}

sub calendarImageWidth {
    my $ctx = shift;
    return $ctx->stash('calendarImageWidth');
}

sub calendarImageHeight {
    my $ctx = shift;
    return $ctx->stash('calendarImageHeight');
}

非常におおざっぱな説明しかできませんでしたが、MovableTypeのプラグインを作成するのは案外簡単であることがわかりました。問題はコンテクストオブジェクトから取り出せるコンテクスト情報の詳細ですね。どなたか整理した人がいたら教えてください。

今回は写真のカレンダー表示をプラグインを作ることで実現しましたが、blogmeterで各種グラフのページを作るのと同じように、外部から記事を読み取って画像のURLを抽出してカレンダーページを作成するようなサービスも実現できると思います。もしかしたら既にあるかもしれません。どなたかぜひ作ってくださいませ。

2005.01.08 (土)

MTPhotoCalendar で写真をカレンダー表示

Adobe Photoshop Albumというデジカメ写真管理ソフトには写真をカレンダー状に並べて表示する機能があります。Casioのデジカメでは液晶画面で写真一覧をカレンダー状に表示できます。写真一覧を時系列に並べるだけでも楽しいんですがカレンダーと組み合わせると、その日に行った場所や会った人、食べたものなどを月日に対応づけて一覧することができるので、日々の生活をありありと思い出してつい見入ってしまうほど楽しめます。

こうしたカレンダー型写真一覧をblogで作ってみたいと思っていました。blogの記事にも写真を載っけてますから、それを抜き出してカレンダー状に並べればよいわけです。きっと誰かが作っているだろうとは思いつつ、勉強を兼ねて作ってみました。 MovableTypeにはテンプレート記述でカレンダーを作る機能がありますから、ちょっとしたプラグインを書くことで実現できました。名付けて MTPhotoCalendar です。できあがったカレンダーはこんな感じになります。

Photo Calendar

このカレンダーを作るには、次のようにします。

  1. MTPhotoCalendar plugin を組み込む。
  2. PhotoCalendarのテンプレートを作成する。
  3. アーカイブを再構築する。
  4. 他のテンプレートへリンクを追加する

順に説明しましょう。MovableType 2.661で作成していますので、3.X系の方は違っているかもしれません。ご注意ください。

MTPhotoClandarの組み込み

まず下記からpluginをダウンロードします。このpluginはフリーで使っていただいてかまいません。

これを展開して、その中の mt-photo-calendar.pl をMTをインストールした場所のpluginsディレクトリにコピーします。pluginの組み込みはこれで完了です。

PhotoCalendar のテンプレートを作成

MTPhotoCalendar pluginを組み込むと、次の4種類のタグがテンプレート記述に使えるようになります。

<MTIfCalendarImage width="nnn" height="nnn" > ~ </MTIfCalendarImage>
当該日にエントリに画像が存在すればタグ内部が有効になる。属性widthとheightでカレンダーの各マスに表示する画像の最大サイズを指定する。
<$MTPhotoCalendarImageSrc$>
当該日のエントリ中の画像のURL。
<$MTPhotoCalendarImageWidth$>
当該日のエントリ中の画像の幅。
<$MTPhotoCalendarImageHeight$>
当該日のエントリ中の画像の高さ。

これらのタグを使って、カレンダー用のテンプレートを記述します。ページ全体は月別アーカイブのテンプレートを使って作成するとよいでしょう。本文部分をカレンダーと置き換えます。カレンダー部分はMTのデフォルトの Main Index のテンプレートに含まれているカレンダー部分をそのまま使うとよいでしょう。私の場合はカレンダー部分は下記のようになります。テンプレートをカスタマイズしているので標準状態のものとは若干異なっています。赤色の部分が今回追加した部分ですので、この部分を同じように追加すればよいでしょう。

<table border="1" cellspacing="0" cellpadding="0">
<caption id="menu">
<$MTArchivePrevious$>
<a href="<$MTArchiveDate format="photo_%Y%m.html"$>">«</a>
</MTArchivePrevious>
<a href="<$MTArchiveLink$>" target="_top">
<$MTArchiveTitle$>
</a>
<$MTArchiveNext$>
<a href="<$MTArchiveDate format="photo_%Y%m.html"$>">»</a>
</MTArchiveNext>
</caption>
<tr>
<th abbr="日曜日" align="center" width="100">
<span class="calendar-head" >日</span></th>
<th abbr="月曜日" align="center" width="100">
<span class="calendar-head">月</span></th>
<th abbr="火曜日" align="center" width="100">
<span class="calendar-head">火</span></th>
<th abbr="水曜日" align="center" width="100">
<span class="calendar-head">水</span></th>
<th abbr="木曜日" align="center" width="100">
<span class="calendar-head">木</span></th>
<th abbr="金曜日" align="center" width="100">
<span class="calendar-head">金</span></th>
<th abbr="土曜日" align="center" width="100">
<span class="calendar-head">土</span></th>
</tr>
<MTCalendar month="this">
<MTCalendarWeekHeader><tr></MTCalendarWeekHeader>
<td align="center" height="85"><span class="calendar">
<MTCalendarIfEntries><MTEntries lastn="1">
<a 
href="<$MTArchiveDate format="%Y_%m.html"$>#<$MTArchiveDate format="%Y%m%d"$>"
target="_top"><$MTCalendarDay$>
<MTIfCalendarImage width="100" height="75">
<br />
<img src="<$MTCalendarImageSrc$>" width="<$MTCalendarImageWidth$>"
height="<$MTCalendarImageHeight$>" border="0">
</MTIfCalendarImage>
</a>
</MTEntries></MTCalendarIfEntries>
<MTCalendarIfNoEntries><$MTCalendarDay$></MTCalendarIfNoEntries>
<MTCalendarIfBlank> </MTCalendarIfBlank>
</span></td>
<MTCalendarWeekFooter></tr></MTCalendarWeekFooter>
</MTCalendar>
</table>

MTIfCalendarImageの内部でMTCalendarImageSrcを使うと、当該日のエントリ中の画像URLを取り出せます。 サイズを指定しているのは、画像の大きさを一定サイズにそろえるためです。別なタグを使って画像サイズを取り出しているのは、横長画像と縦長画像が混在する場合に、どちらの画像も指定した最大サイズに収まるように調整するためです。画像のサムネイルを生成しているわけではなく見ての通り表示サイズを調整しているだけなので、少々画質が粗くなったりするかもしれません。

こうしてできあがったテンプレートをMTに設置します。 MTの「ブログ編集メニュー」画面を開きます。「テンプレートの編集」を選び、「アーカイブに関連したテンプレート」にある「新しいアーカイブ・テンプレートを作る」を実行します。テンプレートの名前を「Photo Calendar Archive」とし、「テンプレートの中身」の欄に作成したテンプレートを貼り付けます。「保存」を押すとMovableTypeにテンプレートが組み込まれます。

次に「ウェブログの設定」を選び、「アーカイブの設定」を選びます。「アーカイブの種類」がMonthlyのところに「Photo Calendar Archive」が現れているはずです。「アーカイブ・ファイルのテンプレート」の欄に「photo_<$MTArchiveDate format="%Y%m.html"$>」と記入します。テンプレート欄は「Date-Based Archive」など既存の月別アーカイブのテンプレートにラジオボタンが付いている状態にしておけばよいでしょう。

アーカイブの再構築

ここまできたら、あとは「サイトの再構築」で「Monthly アーカイブだけ」を再構築してしばし待ちます。再構築が完了したら、「アーカイブディレクトリ/photo_200501.html」のような名前でPhotoカレンダーページができあがっているはずです。 「http://あなたのblogアーカイブパス/photo_200501.html」のようなURLを開いて試してみてください。

他のテンプレートへのリンク追加

ここにインデックスページなどからリンクを張るには、テンプレートで次のように書きます。このblogでは月別アーカイブへのリンクに並べて置いてみました。お試しください。

<a href="<$MTBlogArchiveURL$><$MTArchiveDate format="photo_%Y%m.html"$>">
Photo Calendar</a>

以上のステップを全部完了すれば、これまでに投稿したblog記事の写真を全部カレンダー状に表示することができます。さらに、写真付きの記事を日々追加していくだけで自動的にPhoto Calendarが作られます。ただし、再構築の時間がだいぶ余計にかかるようになってしまいますので、ご注意ください。

写真付きカレンダーで今までの自分の書いた記事を振り返ってみると、単に今までの記事が縦に並ぶアーカイブページを眺めるのとは違った楽しさがあります。人のカレンダーを見ても面白くないでしょうから、ぜひご自分のblogでお試しください。

2004.12.20 (月)

日本販Technorati

このサイトもTechnoratiにpingを飛ばすようにしてますが、Technoratiの検索経由で来る人はほとんどいないようですし、あまり意味ないのかなと思ってました。日本販Technoratiができるならやめちゃってもいいですね。

デジタルガレージ、Technoratiと提携して日本版ブログ検索サイトを開設

デジタルガレージは、米国でブログ検索サービスを提供するTechnoratiと業務提携し、日本国内における独占的な代理権契約を締結したと発表した。これに伴い、2005年1月21日付けで、100%子会社テクノラティジャパンを設立する。  Technoratiは、12月20日現在で500万件のブログサイトと7億3,000万件のリンク情報が検索対象の米国で提供されているブログ検索サービス。同サービスでは、ブログへの書き込みから数分後に更新内容を検索対象に追加できるとしている。

それにしてもものすごい数です。増加率もすごいんではないかと思います。そのうち、これまでの一般Webページの数をブログのページの数が上回る日も来るんではないでしょうか。

[TRN:7588歩]

2004.09.20 (月)

Amazonウィッシュリスト表示方法を変更

このblogではAmazonのウィッシュリストを公開してます。たくさん画像を載せているためページのロードには少々時間がかかると思いますが、ご容赦ください。

時折、ウィッシュリストの一部が正しく表示されないことがあります。ページの再構築の時に aws.pl の呼び出しで何か失敗しているようです。あまり頻繁に起きるので対策を講じてみようと思います。前の記事での改造により再構築時に画像をチェックしてるので、それが重くて失敗してる可能性を考えました。そこで、画像のチェックをページ表示時に行うように変更しました。下記のbulknewsさんのスクリプトを使わせていただいてます。bulknewsさん、ありがとうございます。aws.plの改造の方は元に戻しています。

Amazon の輸入盤画像をいじる javascript: blog.bulknews.net

Amazon Web Services の輸入盤の画像 URL 問題を解消しつつ、さらに画像がなかったら no image の画像を返し、かつサイズを適当にあわせる javascript。

やってみたんですが、結果は変わりありませんでした。この方法でも失敗する時は失敗します。AWS(Amazon Web Service)の呼び出し自体が重くて失敗するんですかね。

2004.08.11 (水)

コメントスパム対策

このサイトにもコメントスパムが来るようになってきた。しばらくは一日1~2個くらいだったんだけど、だんだん増え始めてる。今日は7つだ。いきなり数百個もついたりすることがあるらしいので、一応対策しておくことにする。

まずは、一日数個でも消すのは面倒なので、まとめて消せるようにするために、次の対策を導入する。menu.tmplを置き換えるだけなのでとても簡単。スパムコメントのついたエントリを探したりする手間がいらなくなるので、コメント削除がとっても楽チンになる。Memo Leavesさん、ありがとうございます。

Memo Leaves: 編集メニュー画面からコメントスパムを一括削除

いろいろ試行錯誤した結果、編集メニュー画面に出てる最近のコメントにチェックボックスをつけてDeleteボタンもつけることにした。

次に、そもそもスパムコメントを書き込めないようにする。いろいろな方法があるようだけど、下記の手法を取り入れることにする。コメントを投稿する際にパラメータとして記事のタイトルを渡し、チェックに用いるという方法だ。noblog短気な猫3rdさん、ありがとうございます。 Individual Entry Archive、Comment Listing、Comment Preview、Comment Errorの4つを修正する。 さらに、[MT]/lib/MT/App/Comment.pm を修正する。

noblog::短気な猫3rd: コメントスパム対策

コメントスパムが少し多くなってきたので、Movable Typeのコメントスパム対策をやってみました。 副作用が心配なもの(MTBlackListなど?)は除外して、オーソドックスな方法で入れてあります。 (でも、ちょっと凝った部分もあります)

さて、これで様子を見てみよう。うまくコメントスパムを防止できるかな。

(追記)
対策したとたんにまるで来なくなりました。この方法だとMovableTypeのログに記録が残るんですが、3日後の8/14にようやく1件が記録されてるだけです。

2004.07.19 (月)

輸入版CDも含めてAmazonウィッシュリストをblogに表示する

Amazonのウィッシュリストをblogに表示するのエントリで書いたスクリプトでもやはり輸入版CDの画像は表示されない。そこで輸入版CDでも画像を表示できるAmazonリンク生成スクリプトのエントリと同様の修正を加える。オリジナルのawl.plとの差分は下記の赤いところだ。

sub aws_detail {
    my ($ctx, $e) = @_;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{$e} eq 'ARRAY') {
        #return Jcode->new(join ", ", @{$detail->{$e}}, 'utf8')->utf8;
        return join ", ", @{$detail->{$e}};
    } else {
        if ($e =~ /(ImageUrlSmall|ImageUrlMedium|ImageUrlLarge)/) {
            my $imageUrl = $detail->{$e};
            if (!checkimage($imageUrl)) {
                $imageUrl =~ s/09/01/;
            }
            if (!checkimage($imageUrl)) {
                $imageUrl = "http://images-jp.amazon.com/images/G/09/".
                    "x-locale/detail/thumb-no-image.gif";
            }
            $detail->{$e} = $imageUrl;
        }

        # return $detail->{$e} . Jcode->new($detail->{$e},'utf8')->utf8 || '';
        return $detail->{$e} || '';
    }
}

use Image::Magick;
use LWP::Simple;
sub checkimage {
    my ($url) = @_;
    my $imagedata = get($url);
    my $image = Image::Magick->new;
    $image->BlobToImage($imagedata);
    if ($image->Get('width', 'height') == (1, 1)) {
        return 0;
    }
    return 1;
}

これでウィッシュリストにも輸入版CDが表示されるようになった。

blogにAmazonウィッシュリストを貼るようにしてから一月半ほど立ちますが、これはなかなかいいですよ。Amazonで気になる本やCDを見かけたら、メモする代わりにウィッシュリストに入れればいいんです。自分のblogは毎日目にするわけですから、忘れてしまうことがありません。毎日見るところにメモを書くってのは情報整理の基本のひとつですね。

輸入版CDでも画像を表示できるAmazonリンク生成スクリプト

Amazonリンク生成スクリプトのエントリで書いたスクリプトでは、輸入版のCDの場合に画像が表示されないらしい。Amazon Web Service 側の不具合のようだが、下記の処理をすることで表示できるようだ。

hail2u.net - Weblog - Amazonの画像置換

AWSで返された画像のURLとかAmazonのASINコードから09で類推した画像が、1*1の黒いGIF画像だった場合に、01で類推できるURL無理やり置換してみる実験。

というわけで次のコードを加えてみた。

if (!checkimage($imageUrl)) {
    $imageUrl =~ s/09/01/;
}
if (!checkimage($imageUrl)) {
    $imageUrl = "http://images-jp.amazon.com/images/G/09/".
        "x-locale/detail/thumb-no-image.gif";
}

use Image::Magick;
sub checkimage {
    my ($url) = @_;
    my $imagedata = get($url);
    my $image = Image::Magick->new;
    $image->BlobToImage($imagedata);
    if ($image->Get('width', 'height') == (1, 1)) {
        return 0;
    }
    return 1;
}

これで輸入版でもジャケット写真が表示できるようになった。ほんとはスピリッツオブゼロ@blog - [AWS] Amazon Webサービスの画像置換のようにJavaScriptでページ表示時に判定した方がよいんでしょうね。いつかは本来のURLで画像が表示できるようになるかもしれないから。でもそれもどうなるかわからないから、今は上記のようにしておこう。

スクリプト全体は以前と同じく ここに置いておきます。試したい人は下記でどうぞ。Amazonのページから呼び出すJavaScriptはAmazonリンク生成スクリプトのエントリを見てください。

ISBN:

2004.07.01 (木)

アップロードディレクトリの自動指定

nlog(n): 画像アップロード先の月別指定

このサイトでは、画像のアップロード先を、アーカイブディレクトリ内の年月ディレクトリにしている。例えば、今月であれば 200406 というディレクトリである。毎回このディレクトリを指定するのは面倒なので、テンプレートに手を加える。

この3ヶ月間はimagesというディレクトリに全部の画像を放り込んできたが、さすがに適当な単位で分けておいたほうがよいかと思っていた。この記事はちょうどそれを自動化できるやり方を書いてくれている。これはありがたいということで、早速使わせていだだく。nlog(n)さん、ありがとうございます。少々手を加えて、images-200407のようなディレクトリ名になるようにしました。

2004.06.06 (日)

Amazonのウィッシュリストをblogに表示する

今日はAmazonのウィッシュリストをトップページに表示してみることにする。Amazonのウィッシュリストは気になる本リストとしてとても便利だ。Amazonで気になる書籍を見つけたらすかさずウィッシュリストに入れればよい。クリックひとつの操作だけだ。これをblogのトップページに画像付きで並べられれば、時折眺めては思い出すことができる。ボタンひとつでblogに表示できるので、なかなか悪くない方法だと思う。

ウィッシュリストを取り出すにはAmazon Web Services(AWS)でWishlistSearchという検索を行えばよい。前回作成したスクリプトを拡張すれば簡単に作ることができる。しかし、今回は既存のpluginを使ってみることにした。pluginの組み込み方や、作り方の勉強もしたいからだ。

今回は平田さんのaws.plを使うことにした。平田さんは下記の書籍の著者であり、今では MovableType 開発元のSix Apartの偉い人になっている。

Movable Typeで今すぐできるウェブログ入門
平田 大治


インプレス (2003/08/01)
¥ 1,890
ISBN: 4844318128

さて、aws.plを使う手順は次の通り。デベロッパトークンやアフィリエイトIDの取得は予め行っているものとする。

  1. simple amazon log aws.pl - MT plugin for Amazon webservices からダウンロード、インストール。

    インストール方法は、展開して出てくる aws.pl を mt.cfg を置いたディレクトリの plugins ディレクトリの下に置けばよい。 既に修正版が配布されてるかもしれないが、上記リンクのものはそのままでは動かなかった。aws.pl に以下の修正を加える必要がある。

  2. 「amazon.com」を「amazon.co.jp」に修正。
  3. 「WishListSearch」を「WishlistSearch」に修正。
  4. さらに、perl 5.8の人は次の修正も必要らしい。

  5. のまのしわざ MT plug-in開発の勉強(aws.plの修正)の修正を加える。
  6. ウィッシュリストを表示するには下記のように書けばよい。ウィッシュリストの場合には、ウィッシュリストIDを指定しなければならない。Amazonで自分のウィッシュリストを開いて、作成者の情報の編集ボタンを押してみよう。そのページのURLの一部にウィッシュリストIDは含まれている。私の場合は「2J09IUCQB4QI」となっている。「⇒」のところは折り返さずに1行で書く。

    <MTAws dev_token="デベロッパトークン" associate_id="アソシエイトID"
        search="WishlistSearch" query="ウィッシュリストID">
        <a href="http://www.amazon.co.jp/exec/obidos/ASIN/⇒
        <$MTAwsAsin$>/ref=nosim/アソシエイトID">
        <img alt="<$MTAwsProductName$>" src="<$MTAwsImageUrlMedium$>"
             border=0 />
        <br />
        </a>
    </MTAws>
    

    表示させてみると、ウィッシュリストが10件分表示される。これだけでは寂しいのでもっと表示させよう。AWSでは1回につき10件の検索結果を1ページ分の情報として取得できる。そして、ページ番号を指定することで10件ごとに順次取得することができる。ところが、ウィッシュリスト検索ではパラメータにページ指定が含まれていない。awl.plでもページ指定を渡さないようになっている。これは困った。

    でも実はやってみればできるんである。ページ番号指定はウィッシュリスト検索のドキュメントにはないパラメータだが、指定してみるとちゃんとページごとに検索結果を取得できる。そこで、aws.plを次のように修正する。赤字のところを追加した。もちろん、今回はたまたま動いただけで、今後動かなくなってしまう可能性もあるので注意が必要だ。

  7. 10件を超えるウィッシュリストを表示させる修正を加える。
  8.     'WishlistSearch' => [ "dev-t", "t", "type", "f", "locale", "page" ],
    

    テンプレートに埋め込むタグに下記のようにpage指定を追加する。さらにページ番号のところを2、3と変えて3つほど並べると、ウィッシュリストを30件表示できるわけだ。

    <MTAws dev_token="デベロッパトークン" associate_id="アソシエイトID"
        search="WishlistSearch" query="ウィッシュリストID" page="1">
        <a href="http://www.amazon.co.jp/exec/obidos/ASIN/<⇒
        $MTAwsAsin$>/ref=nosim/アソシエイトID">
        <img alt="<$MTAwsProductName$>" src="<$MTAwsImageUrlMedium$>"
             border=0 />
        <br />
        </a>
    </MTAws>
    

    これで喜んでいたら、30件表示されるはずが数えてみるとどうも数が少々少ないことに気づく。調べて見ると画像が提供されていない書籍やDVDがあることがわかった。画像がない場合には、サイズ1×1の画像ファイルのURLが返ってくるのだ。画像はなくてもリンクだけは表示しておきたいのだが、これではクリックもできない。そこで、少々強引だが、次のような修正を加えてみた。ちょっと無理のあるやり方だが、最小限の変更で済ますためにこうしてみた。追加したのは赤字のところ。

  9. 画像のないアイテムに仮の画像を表示する修正を加える。
  10. sub aws_detail {
        my ($ctx, $e) = @_;
        defined (my $detail = $ctx->stash("Detail")) or return '';
        if (ref $detail->{$e} eq 'ARRAY') {
            #return Jcode->new(join ", ", @{$detail->{$e}}, 'utf8')->utf8;
            return join ", ", @{$detail->{$e}};
        } else {
            if ($e =~ /(ImageUrlSmall|ImageUrlMedium|ImageUrlLarge)/) {
                use LWP::Simple;
                my $data = get($detail->{$e});
                use Image::Magick;
                my $image = Image::Magick->new;
                $image->BlobToImage($data);
                if ($image->Get('width', 'height') == (1, 1)) {
                    return "http://images-jp.amazon.com/images/G/09/".
                           "x-locale/detail/thumb-no-image.gif";
                }
            }
            # return $detail->{$e} . Jcode->new($detail->{$e},'utf8')->utf8 || '';
            return $detail->{$e} || '';
        }
    }
    
    

    これで画像のないアイテムのところには「No image」という画像が表示されるようになった。なお、Amazon側の負荷などの影響か、時折検索結果をうまく得られないことがある。そういう時は、少し時間をおいてから再度リビルドしよう。

やろうとしてたことはひとまず実現できた。平田さんのaws.plは非常に簡潔に書かれていながら、とても汎用にできている。たくさんのことができるのにやたらと行数が短いのだ。しかも今回のようにパラメータを追加するような変更がとても簡単にできる。今後Amazon側でAPIに拡張が加えられても容易に対応できそうだ。このようなスクリプトを提供してくださっていることに感謝します。

トラックバック posted by <蘭の小部屋> | 2004.06.07
黄金花月に大きな材料
黄金花月の別名は「金のなる木」 6日の日曜日に【9479】インプレスにビッグ材料発表がありました。 [6月7日/日本経済新聞 朝刊] ヤフーとインプレス、動画解説入りのネッ

2004.05.30 (日)

Amazonリンク生成スクリプト

Perlの勉強もしたことだし、何か作ってみようということで、amazonのアフィリエイトリンクを生成するプログラムを書いてみた。同様のものは多くの人が作っているので今さら新しくはないのだが、勉強がてらに自分でやってみる。

Amazon Web Service(AWS)を使うとプログラムからamazonの検索機能を呼び出すことができる。試しにやってみるなら、プログラムを書かなくてもこんなフォームを書けば呼び出すことができる。

<form action="http://xml.amazon.co.jp/onca/xml3"
  method="GET" name="aws">
  ISBN:
  <input type="text" name="AsinSearch" value=""/>

  <input type="hidden" name="dev-t" value="デベロッパ・トークン"/>
  <input type="hidden" name="t" value="アソシエイトID"/>
  <input type="hidden" name="f" value="xml"/>
  <input type="hidden" name="locale" value="jp"/>
  <input type="hidden" name="type" value="lite"/>
  <input value="送信" type="submit"/>
</form>

これはISBN番号を入力して呼び出すと、書籍の情報が帰ってくるというものだ。ISBN番号は書籍の裏表紙に定価の近くあたりに「ISBN4-XXXX-XXXX-X」と記してある番号のことだ。4以降の数字を4も含めて、ハイフンを抜いて入力すればよい。自分への覚書として下のフォームで呼び出せるようにしておいた。手元にある本のISBN番号を入力して試してみるとよい。

ISBN:

このフォームを送信して返ってくるのは、XML形式で書籍情報を表したものだ。タグの羅列に埋め込まれるように書籍の題名や著者名が並んでいる。URLはこんな感じになっている。

http://xml.amazon.co.jp/onca/xml3?dev-t=デベロッパ・トークン&t=アソシエイトID&f=xml&AsinSearch=ISBN番号&locale=jp&type=lite

こういうURLを生成して呼び出せば、XML形式で書籍の情報が返ってくるということだ。これがRESTと呼ばれる呼び出し方法の基本的なしくみだ。AWSではRESTの他にSOAPという方式で呼び出すこともできるのだが、この程度の使い方には冗長過ぎる方式かもしれない。それに、SOAPでは文字コード周りで少々工夫が必要らしい。

では、このURLをperlで生成しよう。これは簡単だ。

sub amazon_query_url_isbn {
    my $isbn = shift;

    "$amazon_query_url?"
    . "dev-t=$amazon_dev_token&"
    . "t=$amazon_affiliate_id&"
    . "f=xml&"
    . "locale=jp&"
    . "type=lite&"
    . "AsinSearch=$isbn";
}

これを呼び出して結果を受け取るには、LWP::Simpleを使ってこうやればよい。

use LWP::Simple;
my $xml = get(amazon_query_url_isbn($isbn));

さて、帰ってきたXML形式の情報は、XML::Simpleを使って分解してみよう。

use XML::Simple;
my $tree = XMLin($xml, ForceArray=>1, KeyAttr=>[]);
my $book = $tree->{"Details"}->[0];

XMLがperlのハッシュと配列でツリー状に展開される。データ構造としては非常に複雑だが、それこそこの本で勉強したかいがあるというものだ。ここから個々の情報を取り出すにはこんなふうにすればよい。

sub getValue {
    my ($tree,  $tag) = @_;
    return join(', ', @{$tree->{$tag}});
}

要素が複数個ある場合には「,」で繋げて並べるようにしている。著者名は階層が1段深いので下記のようにする。書籍ではなくCDやDVDの場合にも使えるようにしてみた。

sub getAuthors {
    my $detail = shift;
    if ($detail->{"Authors"} != undef) {
        return getValue($detail->{"Authors"}->[0], "Author");
    } elsif ($detail->{"Artists"} != undef) {
        return getValue($detail->{"Artists"}->[0], "Artist");
    } else {
        return ;
    }
}

これらを使うと、個々の書籍情報はこんなふうに取り出せる。

my $title        = getValue  ($book, "ProductName");
my $author       = getAuthors($book, "Author");
my $manufacturer = getValue  ($book, "Manufacturer");
my $imageUrl     = getValue  ($book, "ImageUrlMedium");
my $price        = getValue  ($book, "OurPrice");
my $asin         = getValue  ($book, "Asin");
my $releaseDate  = getValue  ($book, "ReleaseDate");
my $imageUrl     = getValue  ($book, "ImageUrlMedium");

あとは、これを好きなように加工して使えばよい。アソシエイトID付きのリンク付き書籍情報として表示してみる。下のフォームから呼び出せるようにしておいた。手元の書籍のISBN番号を入力してみるとよい。

ISBN:

表示されたHTMLタグをblogなり、webページなりにコピー&ペーストすれば画像付きアソシエイトリンクのできあがりだ。さっそく作ってみたのがこれだ。

Amazon Hacks 世界最大のショッピングサイト完全活用テクニック100選
ポール・ボシュ, 篠原 稔和, ウェブ・ユーザビリティ研究会


オライリー・ジャパン (2004/04/24)
¥ 3,045
ISBN: 4873111811

フォームにいちいちISBN番号を入力するのは面倒くさい。そこで、javascriptで自動化してみよう。amazonの商品ページを開いている状態で上記フォームを呼び出すスクリプトはこうなる。

javascript:var%20id='アソシエイトID';var%20u=document.location.href;var%20i=u.indexOf('ASIN');var%20asin=u.substring(i+5,i+15);void(window.open('http://blog.bibinko.com/cgi-bin/amazon-isbn.cgi?asin='+asin+'&t='+id))

このスクリプトを実行するには、まずこのAmazonリンク作成リンクを、リンクバーにドラグ&ドロップする。そして、Amazonの商品ページを開いた状態でリンクバーからこのリンクを呼び出すとフォームを送信するのと同じ処理が実行される。こういうスクリプトをbookmarkletと呼ぶらしい。リンクのプロパティを開くと、URLのところにスクリプト本体が入っている。先頭の方にアソシエイトIDが入っているので、自分のIDに修正して使えばよい。

AWSでは、XSLTというXMLの処理系を使うことができ、Perlなどでプログラムを書かなくても同じことができる。XSLTでXMLからHTMLへの変換規則を記述し、そのファイルのURLをAWS呼び出し時に渡しておけばよいのだ。この方法もそのうち勉強がてら試して見よう。

Amazonのアソシエイトプログラムでは、リンク作成のページで商品へのリンクを作成することができる。そのページの中で、イメージのコピーもできるようになっている。画像をローカルにコピーしてしまえば、amazon側の負荷を減らせるのでできればコピーしてしまいたい。ところが、 Amazon.comWebサービス 使用許諾条件には下記のように記述されている。

Amazon.comWebサービス 使用許諾条件

貴方は、24 時間までの間、貯蔵(キャッシュ)目的でAmazon.com の知的財産を格納することができます。

AWSを使ったサービスでは画像を24時間までしかローカルに保持できないのだ。これでは画像どころか、書名や著者名さえもローカルに保持することができなくなってしまう。これに関しては次のように考えることにした。AWSによる書籍情報表示サービスと、それを活用してアフィリエイトリンクを提示することをそれぞれ独立な行為と考えるのだ。前者は情報をその場で表示するだけで、保持し続けることはない。後者では前者で得た情報をアフィリエイトリンク作成のために使用する。実際、前者と後者は別な人が提供することができるので、分離して考えることは合理的であろう。その意味でも、blogのエントリまで自動生成したりせず人手によるコピー&ペーストを介しておくのがよさそうだ。

それでは、この考え方で画像もコピーできるのだろうか。前述のリンク作成のページでのイメージコピーのところでは、商品によって商品の画像が提示されるものとされないものとがある。いくつか試してみたところでは、書籍では提示されず、CDやDVDでは提示されるようだ。wadさんによると和書とXbox本体以外に関してはamazonがアソシエイト先に画像をサブライセンスする権利を持っているらしい。

wad's更新記録

amazon.co.jpに問い合わせたところ、「和書およびXbox本体」以外の画像については、アソシエイトが自分のサイト上で自由に表示できるという答えをもらいました。 これ以降の記述には、私の解釈が入っている部分があります。 「和書およびXbox本体」以外の取り扱い品目については、amazonは、アソシエイトに画像の使用をサブライセンスするライセンスを、それらの画像の著作権者から得ているということです。また、amazonのサイト上にある「画像ファイル」そのものは、amazonが作成したか使用許諾を受けたものなので、amazonのサイトからコピーして使っても問題はありません。 「和書およびXbox本体」の商品については、各発売元の許諾を得る必要があります。実際、amazon.co.jpのリンク・ジェネレータでは、和書とXbox本体については、イメージ・リンクに使用する画像として、「Amazon.co.jpで買える」というジェネリックな画像が表示されます(すべて調べたわけではありませんが)。

今現在でもこの条件のままだとすると、洋書やCD/DVDならイメージのコピーができるが、和書ではできないということになる。実際にコピーする際には、Amazonのリンク作成ページで確認するか、Amazonに条件を問い合わせてから行うべきだろう。

画像をコピーできるものに関しては、次のようなコードでコピーすることができる。

my $MTImagePath   = "画像ファイルの置き場所";
my $filename = $imageUrl;
$filename =~ s#.*/##;
my $path = $MTImagePath . "/" . $filename;
getstore($imageUrl, $path);

今のところコピー可能な画像かどうかを自動的に判別する方法がわからないので、前述の確認を行った上で使い分けるしかないだろう。今回作成したスクリプトからは、画像のコピー機能ははずしてある。コピーしなくとも、イメージを参照して自分のサイトに埋め込んで表示することはグレーゾーンだと思われる。世間ではこのような表示が普及しつつあるようなのでそれに従ってみるが、問題があるようならすぐにはずしたい。

ISBN番号での検索以外にもキーワード検索や著者名での検索などいろいろな検索ができる。そうした検索にも必要が出てきたら対応しよう。今のところAmazonのサイトで検索して、書籍情報をクリップしてこのサイトにアフィリエイトリンクを張る程度なのでこのスクリプトくらいで十分だ。できあがったPerlスクリプトをここに置いておく。デベロッパ・トークンのところを自分のものに修正すればそのまま使えるはずだ。自由に改変して使ってもらってかまわない。表示形式をなどを自分好みにカスタマイズするとよいだろう。

せっかく作ったので、過去のエントリのアフィリエイトリンクも作り直しておこうかな。

コメント <1> Posted by tama | 2004.07.19

輸入版CDの時に画像が出なかったんで、輸入版CDでも画像を表示できるAmazonリンク生成スクリプトに修正版を載せました。

2004.05.05 (水)

曜日入れ替わり問題

日付のところに曜日を入れようと思って、フォーマット指定に %a を入れると「月」のような表示になるはずが変な文字化けになる。%A にすると「月曜日」のように正しく表示される。でもよくよく見ると水曜日と木曜日が逆になってる。なんだこりゃ。

自分でコードを追っかけるのは面倒なのでWebで探してみると、やっぱり解決してくれてる人がいました。きゃんころさん、ありがとう!活用させていただきました。

きゃんころ: MOVABLETYPE曜日問題

MOVABLETYPEを日本語で使っていて、日付に曜日を表示させると水曜日と木曜日が入れ替わってしまうという問題が発生しました。
...
簡単に言うと、文字そのものでなく「漢字コード」でコーディングされていたところが間違っていたためです。

MT 和風日付表示プラグインというのを使うと休日名を表示したりもできるらしいんだけど、それはまた今度にしておこう。

2004.05.04 (火)

Individual Entry Archive 文字消え対策

個別のエントリごとのページを開くと、文字が一瞬表示されるものの直後に消えてしまう症状に悩まされていた。マウスでなぞって選択すると表示されたりするのだが開いた直後には何も表示されない状態なのだ。これではまずいので、じっくり調べてみた。

スタイルシートやテンプレートを少しずつ変更して様子を見たところ、コメント記入欄にある float 指定と、ブロックに対する背景色指定が複合して現象が発生するようだ。どちらかを削ると文字は表示されるからだ。この症状をWebで探してみると、こんなページが見つかった。

Internet Explorer (Windows) CSSバグリスト

背景色が指定された要素内にフロートがあるときに要素内の文字が消える(IE6)

まさにこの症状だ。このページの対処法に従い、該当のブロックである comments-body に width: 90% を加えてみた。見事へんてこな現象は回避された。めでたし。

2004.04.12 (月)

DOM Inspecter

Going My Way: divで囲まれた要素を表示するDOM Inspecter

Cartapacioで紹介されていた