2008年4月アーカイブ

Adobe GoLive 9がディスコン。ていうはなし。

InDesign居残り補習室 GoLive 9 開発および販売終了 [kstation2.blog10.fc2.com]

GoLive9、去る4月28日で開発および販売終了だそうですね。
GoLiveユーザーのため、AdobeはDreamweaverCS3に安く移行できる価格を用意しているようです。

ソフトウェア開発リソースというのは限度があるわけで、Adobe Systems Inc.も企業であるからリソースを割けない製品をディスコンにするのは当たり前の話しで、それはそれでやむを得まい、と思います。

しかし、ソフトウェアの商売っていうのは、ベンダ側の都合だけではなく、利用者側の都合もあるわけで、毎度の事ながらAdobe Systems Inc.のやり方、需要があるにもかかわらず販売終了、ていうのは利用者の都合を無視した話しであり、Adobe Systems Inc.のみならずアドビシステムズ株式会社が嫌われることになるきっかけを毎回毎回自分で作っているわけで。

販売継続を続けることで販売に関するコストがかかるだろって言うのは、自慢のアドビストアでダウンロード販売のみにすればいいし。

サポートコストかかるだろ、ていうのは、サポートだけ終了、過去のサポートデータベースは公開したまま、ていうことでいいだろうし。

ディスコン製品のアクティベーションしなきゃいけないだろ、ていうのはAdobeが会社として存続する限りアクティベーションシステム動かさなくてはならないし。

ディスコンていうのはベンダ側のディスコミュニケーションでもあるけれども、上記のような策をすることで、利用者側からのコミュニケーションチャンネルを確保することが出来て、ベンダと利用者の相互理解が(それなりに)出来るものと思います。

相互理解、そこが問題で、同じく先日ディスコンになったQuarkXPress 4.1Jの場合、「発売からもう10年だし、今更Mac OS 9の製品でもないよね? もういいよね?」という心情は最近のQ社の動向と相まってビンビン伝わってきて、「まーしょうがないかなー」とつい納得してしまうのです。相互理解には情緒的なものが充分絡んでいます。

そういう意味で、ソフトウェアっていうのは、製品の購入にて発生する契約とは別に、そのソフトウェアをどうしても使いたい、と思う利用者の意志があって、現在のとあるソフトウェアベンダはユーザの意志との自社の都合とのすりあわせをするという意識に乏しいなあと思います。

迷った

| コメント(0) | トラックバック(0)

明日クルマで納品があるのだけれども場所が行ったこと無いところなのでちょっと不安に感じ、実際に片道1時間かけて明日行く場所にあらかじめ行ってみたら案の定迷いました。何で市内って一方通行ばかりなんやー

みんなの地図2つかったら、橋を降りた先の道がいつの間にかできあがりやがっていて、突き当たりを左と暗記していた僕はあさっての方向に走って行ってしまったのでした。

今日迷っておいてよかったです。

なぜかQuarkXPress 4.1Jが手に入ったので、うちのMacに、QuarkXPress 4.1Jを入れました!

Winmacqx41s
▲MacはVNCで使います

ドングルもぴちぴちしていて元気です!

これからばりばり検証します!

Windows IE6は、XML宣言があると後方互換モードでレンダリングされる不具合があるので、標準準拠モードにするにはXML宣言を取っ払う必要がある。他のブラウザはそういう問題がないので、XML宣言つけておきたい。というときに、CGI::Applicationで、能動的にプラウザの種類によって吐き出すHTMLを変えてやろうという魂胆です。

CGI::Applicationでは、cgiapp_postrunで、吐き出す寸前のコンテンツを書き換えることが出来るので、ここで、ブラウザがIE6で、かつContent-Typeがtext/htmlの時だけ、XML宣言を取っ払うコードを書いておけばOK。

CGI::Application::Plugin::BrowserDetectが初めて役に立ちました。

#!/usr/bin/perl
package main;
my $webapp = WebApp->new();
$webapp->run();
 
 
package WebApp;
use base 'CGI::Application';
use strict;
use warnings;
use CGI::Application::Plugin::BrowserDetect;
 
 
sub cgiapp_postrun {
  my $self = shift;
  # WinIE6の時にXML宣言を外す
  my $output_ref = shift;
  my $b = $self->browser;
  if ( ({$self->header_props()}->{'-type'} eq 'text/html') &&
       ( ( $b->windows ) && ( $b->ie )
         && ( $b->major < 7 ) ) ) {
    $$output_ref =~s/<\?xml .+\?>\n?//so;
  }
}
 
 
sub setup {
  my $self = shift;
  $self->start_mode('start');
  $self->run_modes(
    start => 'start',
  );
  $self->header_add( -type => 'text/html',
                     -charset => 'UTF-8' );
}
 
 
sub start {
  my $self = shift;
  my $tmpl_html = << 'END_OF_HTML';
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC 
  "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xml:lang="ja" lang="ja">
  <head>
    <meta http-equiv="Content-Type"
      content="text/html; charset=UTF-8" />
    <title>test</title>
    <meta http-equiv="content-script-type"
      content="text/javascript" />
    <meta http-equiv="content-style-type"
      content="text/css" />
    <link rel="index" href="/" />
    <link rev="made" href="mailto:hoge@example.com" />
  </head>
  <body>
    <p>
      IE6だとXML宣言消えているよ。
    </p>
  </body>
</html>
END_OF_HTML
  my $t = $self->load_tmpl( \$tmpl_html );
  return $t->output;
}

PDF 千夜一夜: 文字をパスで表した場合とグリフで表した場合の違い [blog.antenna.co.jp]

Word2007で数式編集したとき、それをPDF化すると数式の文字をパスに変換してしまうという問題が発生して、それを調査した話です。
Publishing Workflow – Math content as paths vs glyphs in generated PDF files

PDFの中で、文字をパスで表すかグリフで表すかは、一見大きな違いがありませんが、拡大するとその相違が分かります。文字の輪郭をパスで表した場合、これを拡大するとパス同士の接続が滑らかでなくなってしまっています。このため、文字の輪郭が滑らかでなくなります。(600%拡大の上の画像)

これと似たような現象を見たことがあるような気がしますが、思い出せません。

一太郎ですね。

一太郎の印刷機能では、PSを一太郎が自分で生成することができるのですが、そのときプリンタドライバに設定されている解像度が低いと、文字がふにゃふにゃになりますので、一太郎からPS書き出しするときは、解像度を思いっきり高くしておくのがポイントです。

あと、WMFによるエクスポートするとこうなるソフト多かったと思います。

これおそらくWindowsのGDIの制限だと思います。

10年前ぐらいからWindowsの出力やっている人だと結構目の当たりにしているじゃないかなと思われます。

昨日書いたエントリで、

はてなブックマーク - M.C.P.C.: 取り入れるにしても根拠をしっかり [b.hatena.ne.jp]

それなら白バックはWeb界から無くして欲しい。写真との兼合いで。

というはてブのコメントが付いていますけれども、当分は白バックって無くならないと思うんですよね(ちなみにこの項では写真との兼ね合いでとかは考えませんのであしからず)。

カラーモニタで白バックで黒文字がにじまなくなったのがWindows3.1の頃ですよね。MAGがモニタ出していた頃。

(Macは発売当初から白バック黒文字でしたが、モノクロブラウン管でにじまないのはそんなに難しい話しではない。画面の解像度稼がなくてはいけないワークステーションはモノクロが多かったですよね。)

特に今はLCDモニタがあり、ピクセルと発光体が1対1対応する夢のデバイスが実現できています。アンチエイリアス好まない人っていうのは、FM-8のV-RAM48KBで1ピクセルごとに色づけ可能やったぜ!とか言いながらやってみるとモニタ上ではにじんでしまい目に涙もにじんでしまった世代が言うているのもしれません。モニタの電子ビームを調整しようとしてトリマー回して感電したりして。

そんで、今は白バックの中に色文字置いてもにじまないんだ! ていうことで画面上で無茶してもいい時期。実際僕も、HTML書いていて、コントラスト差が小さい色で1px罫を引いても大丈夫な点がスゲエお気に入りです。

Mosaic・初期のNetscapeのデフォルトのバックはグレーでしたけど、今のWebブラウザのデフォルトのバックはみんな白バック。基本的にWebは紙のメタファーという立場を取っているかぎりバック白は無くならんし、それベースでみんないろんな色を置いてみるんだと思います。

個人的には、AdobeがFlexでビミョーな青バックをデフォルトにしていたり、LightRoomで黒バックをデフォルトにしているのが気になりますね。紙はAcrobatに任せて、それ以外では紙のメタファーをもう必要としないんだな。

テキストカラーの変更 - MACお宝鑑定団 blog [www.macotakara.jp]

Web業界で、新しい流行を積極的に取り入れているAppleが

http://www.apple.com/jp/hotnews/

サイト上のテキストに関するカラーを以下のように変更してます。

見出し #333333

本文 #585858

リンク #2971a7

これにさっそく習ってみたのですが、どうでしょう?

どうでしょう、ていうので思ったことを言いますけれども、Appleとやらが、そのカラーをはたして流行だからということだけで取り入れたかどうかしらんし、それを無批判に採用してしまうことに疑問を感じました。

~~~

本文テキストにグレーを使い、バックの白地とのコントラスト差を小さくするのは、MTのデフォルトテンプレートなどでも結構前からやられていたように感じています。また、アンチエイリアス前提の表示系であれば、コントラストの差を小さくすることで、アンチエイリアス部の中間調表現も穏やかになるでしょうから、なめらかな文字の表示に貢献するかもしれませんね。

ちなみに、紙の世界では、本文をグレーにするのは、文字がスミの網点で表現されてしまうので、結構御法度であります。

EDGE Now!からやってきたWebを取得するbotがUser-Agentをはいていない疑いがある件は前書きましたが、

EDGE Now!から1日12回やってくるはずのフィード取得botも、どうやらUser-Agentをはいていないような気がします。

FeedBurnerの一覧に載ってこないのです。

User-Agentはちゃんと名乗りましょうと、お母さんや先生に教わらなかったのでしょうか。

僕は、アドビからHTMLを引っ張ってきてRSSを出すスクリプトでは、User-Agent名乗っています。

【疑問】組版の基礎を座学で習うなら何時間必要か?【珍問】 [dslabo.blog4.fc2.com]

という疑問が生じたりしてます。
いや1日じゃ明らかに足りんなあと思ったので。

これ普段の生活の中で組版にどれだけ「気づいているか」という問題になるんだと思います。小学校の時に縦組みの書籍の内容よりも紙面の中のルールに興味が行ってしまい大まかなルールが身についてしまっている人もいるけれども、初任者で配属された時にはじめて気づく人もいて、習得する速度もかなり差が出るように思いますよ。

そういう意味で、自分の経験に基づき、自分の学習方法をなぞるやり方が必ず成功するとは限らないのではないかなあと思いました。

# 普段から「気づいていた」人が必ずこの業界に来てくれるという訳ではない部分がちょっとつらいのかもしれません。

EDGE Now!はアドビのサイトなんですけれども、下のスクリーンショットは、参加者が入ることができる、コントロールパネルページ。

Adobeblogger
▲上から目線

アドビはみぞぎなど永遠に済まんほどの禍根を残しつつ一方でアドビ様とあがめろーて言うているわけですかー

もっともアドビが振りまいた災いのほとんどは日本法人のせいじゃなくて本社決定なんだろうからかわいそうではあるとおもいます。

かくいう僕もすごく嫌われていますが、定量的にどのほどかは知りません。

YahooのWebサービスで、形態素解析ができるやつがあるので、

Yahoo!デベロッパーネットワーク - テキスト解析 - 日本語形態素解析 [developer.yahoo.co.jp]

使ってみました。GETバージョンとPOSTバージョンを二つ作ってみました。というのも、最初楽チンなほうのGETバージョンを作りましたが、これってYahooのWebサーバソフトの制約であまり長い文字列渡せないよなーと思って、POSTバージョンを追加で作りました。

なお、アプリケーションIDは各自自前で取得してください。

Filename: parse_get.pl

#!/usr/bin/perl
use strict;
use warnings;
use Encode;
use LWP::Simple;
use utf8;
use URI;
use XML::Simple;
binmode STDOUT => ':utf8';
 
# __END__以降一気読み
my $text; { local $/ = "\0"; $text = <DATA>; }
 
my $ref = yahoo_parsetext_get( $text );
foreach my $item ( @{$ref->{uniq_result}->[0]
                   ->{word_list}->[0]->{word}} ) {
  print "$item->{count}->[0]\t$item->{surface}->[0]\n";
}
 
exit;
 
 
sub yahoo_parsetext_get {
  my $text = shift;
  my $proxy = 'http://api.jlp.yahoo.co.jp/MAService/V1/parse';
  my $uri   = URI->new( $proxy );
  $uri->query_form(
    appid       => 'xxxxxxxx',
    results     => 'uniq',
    response    => 'surface',
    uniq_filter => '9', # 名詞
    sentence    => encode('utf8', $text),
  );
  my $xml = get($uri->as_string);
  my $xs  = XML::Simple->new();
  my $ref = $xs->XMLin( $xml, forcearray => 1 );
  return $ref;
}
 
 
__END__
昨日長岡技術科学大学で行われたオープンソースカンファレンス 2008 Nagaokaに行ってきました。
 
http://www.ospn.jp/osc2008-nagaoka/
 
 
▲長岡技科大は学内桜だらけでいいねー
 
まあ、講義棟がどこだか分からず奥までいってしまったわけですが。
 
普段の出張だったらスーツ着用ですが、今回は私用なので私服でいったら見事学生に紛れてよかった(つもり)。
 
参加したのは、
OSS事例紹介「システム会社と二人三脚で段階的にITシステムを強化」
Railsで作る社内システム ~ワークフローシステム開発事例紹介~
MediaWikiでコミュニケーション
データベースをアプリに組み込もう!~実践Firebird / MySQL / SQLite~
 
の4つ、あと閉会式&抽選会。
 
んで、情報系の大学に入ったつもりだったのに講義が顎関節とか機能的電気刺激とかサイバーパンクあふれる講義ばかりでドロップアウトしてしまった僕にとっては、ふつーにソフトウェア関連の発表を見るのは新鮮でした。
 
参考になったのは最後のセミナーかな。SQLiteでいいんだっていう自信になったw
 
 
▲こういうプロダクト別比較表って助かるよね
 
このセミナーの開催を教えてくれたS君ありがとう。
 
※抽選会で景品当たらなかった。ちえっ。

Filename: parse_post.pl

#!/usr/bin/perl
use strict;
use warnings;
use Encode;
use HTTP::Request::Common qw(POST);
use LWP::UserAgent;
use utf8;
use XML::Simple;
binmode STDOUT => ':utf8';
 
# __END__以降一気読み
my $text; { local $/ = "\0"; $text = <DATA>; }
 
my $ref = yahoo_parsetext_post( $text );
foreach my $item ( @{$ref->{uniq_result}->[0]
                   ->{word_list}->[0]->{word}} ) {
  print "$item->{count}->[0]\t$item->{surface}->[0]\n";
}
 
exit;
 
 
sub yahoo_parsetext_post {
  my $proxy = 'http://api.jlp.yahoo.co.jp/MAService/V1/parse';
  my $request
    = POST( $proxy,
            [
              appid       => 'xxxxxxxx',
              results     => 'uniq',
              response    => 'surface',
              uniq_filter => '9', # 名詞
              sentence    => encode('utf8', $text),
            ]
      );
  my $ua  = LWP::UserAgent->new;
  my $res = $ua->request($request);
  my $xml = $res->content;
  my $xs  = XML::Simple->new();
  my $ref = $xs->XMLin( $xml, forcearray => 1 );
  return $ref;
}
 
 
__END__
昨日長岡技術科学大学で行われたオープンソースカンファレンス 2008 Nagaokaに行ってきました。
 
http://www.ospn.jp/osc2008-nagaoka/
 
 
▲長岡技科大は学内桜だらけでいいねー
 
まあ、講義棟がどこだか分からず奥までいってしまったわけですが。
 
普段の出張だったらスーツ着用ですが、今回は私用なので私服でいったら見事学生に紛れてよかった(つもり)。
 
参加したのは、
OSS事例紹介「システム会社と二人三脚で段階的にITシステムを強化」
Railsで作る社内システム ~ワークフローシステム開発事例紹介~
MediaWikiでコミュニケーション
データベースをアプリに組み込もう!~実践Firebird / MySQL / SQLite~
 
の4つ、あと閉会式&抽選会。
 
んで、情報系の大学に入ったつもりだったのに講義が顎関節とか機能的電気刺激とかサイバーパンクあふれる講義ばかりでドロップアウトしてしまった僕にとっては、ふつーにソフトウェア関連の発表を見るのは新鮮でした。
 
参考になったのは最後のセミナーかな。SQLiteでいいんだっていう自信になったw
 
 
▲こういうプロダクト別比較表って助かるよね
 
このセミナーの開催を教えてくれたS君ありがとう。
 
※抽選会で景品当たらなかった。ちえっ。

実行例:

$ perl parse_post.pl
4	システム
3	講義
2	2008
2	SQLite
2	セミナー
2	事例
2	抽選会
2	紹介
1	-nagaoka
1	4
1	Firebird
1	IT
1	MediaWiki
1	MySQL
1	Nagaoka
1	OSS
1	Rails
1	http
1	jp
1	osc
1	ospn
1	www
1	ちえ
1	つもり
1	どこ
1	ふつー
1	わけ
1	アプリ
1	オープン
1	カンファレンス
1	コミュニケーション
1	サイバーパンク
1	スーツ
1	ソフトウェア
1	ソース
1	データベース
1	ドロップアウト
1	フロー
1	プロダクト
1	ワーク
1	二人三脚
1	今回
1	僕
1	出張
1	刺激
1	参加
1	参考
1	君
1	大
1	大学
1	奥
1	学内
1	学生
1	実践
1	強化
1	情報
1	技
1	新鮮
1	昨日
1	普段
1	景品
1	最後
1	桜
1	棟
1	比較
1	発表
1	着用
1	社内
1	私服
1	私用
1	自信
1	長岡
1	長岡技術科学大学
1	閉会
1	開催
1	開発
1	関連
1	電気
1	顎関節
1	w

これ何に使うかっていうと、自動タグ付けに使えないかなーて思っとります。

Adobe 9/DIAMOND

| コメント(0) | トラックバック(0)

Adobe Acrobat 9の機能が明らかに - ITmedia Biz.ID [www.itmedia.co.jp]

 米Adobe Systemsは2008年夏に、次期版Acrobatプラットフォームを「Adobe 9」の名前でリリースする見込みであり、その詳細な機能が明らかになり始めたと情報筋が伝えた。

に対する反応で、

Acrobat9では名前が変更に→Adobe 9 - DTP+印刷営業メモ

会社名を製品名にするなんて…。

なんていうのがありまして、プラットフォームの名前がAdobe 9だということですが、プラットフォームの名前と製品の名前の関係がよくわからなんだ。

マイクロソフトのOffice 2007は、おそらく、プラットフォームの名前としてはMicrosoft Office System 2007、製品としては、Microsoft Office Word 2007とかだったと思うので、もしかしたらAdobe 9も、その程度の話かもしれないですね。ベンダが製品群を説明するときにAdobe CS 4シリーズがどーたら、という感じでAdobe 9シリーズがどーたら、ていう説明の仕方をして、うちらユーザーにとってはAdobe 9という名前はDでもE感じになると予想。

どうせビュアーソフトはAdobe Reader 9なんだろうから、Adobe 9シリーズのAdobe Reader 9ていうことで統一感だけは出ますよね。

そんで、社名を製品名にする関係で、つい最近、三菱重工のオフセット枚葉印刷機がDIYAからDIAMONDに変わったことを思い出しました。

去年のIGASあたりの話だったかなー

三菱重工 紙・印刷機械事業部|枚葉印刷機の新鋭機「DIAMOND 300」を投入 7年ぶりのフルモデルチェンジ機、生産性と操作性を大幅に向上 [www.mhi.co.jp]

よくあるんとちゃう? 三菱の場合、ダイヤモンド関連の名前つけたがるダイヤモンド病なんですけれども。

そんで、三菱とアドビの共通項としていえるのは、自社の名前をかっこいいと勘違いしていることだと思いました。

大塚商会のAppleTipsというPodCastプログラムがありまして、

Apple Tips 第54回 今だから語れるクリエイティブ環境との接し方 その1 アプリケーション・OS・ハードウェアの進化との上手な付き合い方 | 大塚商会
Apple Tips 第55回 今だから語れるクリエイティブ環境との接し方 その2 今後のクリエイティブワークで求められること | 大塚商会
Apple Tips

前回の54回、今回の55回はアドビやアップルに在籍した百合さんが出演していましたが、

発言がことごとくソフトウェアを殺そうとしている発言で悲しくなってきます。

~~~

いいソフトウェアには、計算機を宿主、人間を媒介として自己を保存・複製をしていく生命体にも似たところがあるんですけれども、現実には、著作権などの法律だったり商業活動だったり、コードパクったといわれるとイヤだとか、何らかのソフトウェアの外の世界の縛りがソフトウェアの繁殖活動を抑制するものになっていますよね。

んで、アップルやアドビは、自らが生み出したソフトウェアを殺そうとしている部分がありますよね。

ソフトウェア技術者であれば、自分が作ったソフトが長く使われていることにこそ誇るべきなのにねー。販売営業になるとそうもいかないんだろうなあ、と思いました。

EDGE Now!のリンク件数を返す野良API(XML-RPC)で提供しているXML-RPCインターフェースのプログラムです。

問い合わせがあったURLを、以前作ったEDGE Now!外部DBに問い合わせすると、EDGE Now!の内部のサイトIDが得られます。そのサイトIDを、EDGE Now!内部のAPIに投げて、紹介した人の人数を取得します。

なお、XML-RPCの呼び出し方法は、上記リンク内で書いていますが、はてなに合わせていますw

#!/usr/bin/perl
use strict;
use warnings;
use XMLRPC::Transport::HTTP;
 
XMLRPC::Transport::HTTP::CGI
  -> dispatch_to('link')
  -> handle;
exit;
 
 
package link;
  
use strict;
use warnings;
use CGI;
use DateTime::Format::MySQL;
use DBI;
use LWP::UserAgent;
use URI;
use XML::Simple;
use XML::RSS;
use utf8;
binmode STDOUT => ':utf8';
 
sub getCount {
  shift if UNIVERSAL::isa($_[0] => __PACKAGE__);
  my $self;
  @$self = @_;
 
  our $referer = 'http://labo.dtpwiki.jp/edgenow/bloggerslist.cgi';
  our $ua = LWP::UserAgent->new;
  $ua->timeout(10);
  $ua->agent("bloggerslist/0.1($referer)");
  our $dbh = DBI->connect('dbi:SQLite:dbname='
                         .'edgenow_sites.db',
                         undef, undef , {AutoCommit => 0} );
  my $res = {};
  foreach my $item ( @$self ) {
    $res->{$item} = _db($item);
  }
  return $res;
};
 
sub _db {       
  my $url = shift;
  our $dbh;     
  $url =~ s|/$||;
  my $sth = $dbh->prepare("SELECT * FROM urls WHERE url = ?");
  my $result = $sth->execute($url) || die $!;
  my $ref = $sth->fetchrow_hashref;
  my $entryid = $ref ? $ref->{entryid}: undef;
  $dbh->commit;
  return 0 unless $entryid;
  my $hash = get_EDGENow_indivisual($entryid);
  my $items = $hash->{bloggerList}->[0]->{blogger};
  return scalar @$items;
}
 
sub get_EDGENow_indivisual {
  my $id = shift;
  our $referer;
  our $ua;
  my $proxy = 'http://edgenow.jp/xml/bloggerSite.php';
  my $uri = URI->new( $proxy );
  $uri->query_form(
    id => $id,
  ) if $id;
  my $req = HTTP::Request->new(GET => $uri->as_string);
  $req->referer($referer);
  my $res = $ua->request($req);
  my $xml = $res->content;
  my $xs = new XML::Simple();
  my $ref = $xs->XMLin( $xml, forcearray => 1 );
  return $ref;
}
 
 
1;

使用例は、M.C.P.C.: EDGE Now!リンク数野良APIサンプルプログラムに出してあります。

このプログラムは、URLに対して何か情報を返すXML-RPCインターフェースの実装例としてお使い頂けるかと思います。

EDGE Now!は、紹介したURLの先のデータを取得して、HTMLであればtitle要素のところを取得し、EDGE Now!内部のDBに登録するわけですが、

http://labo.dtpwiki.jp/user_agent/user_agent.cgi

のような、アクセスしたブラウザ・bot・クローラのUser-Agentをtitle要素にするようなCGIを作って仕込んでおくと、EDGE Now!の次のクローリング時に、EDGE Now!のクローラ自身のUser-AgentをEDGE Now!にさらすことになるはずです。

というわけで次のクローリングで確認できたらスクリーンショットとってここに追記しようかなーと思っています。

なお、このCGIの中身については、

M.C.P.C.: SBMのロボットのUserAgent名が分かるCGIスクリプト

をどうぞ。


(2008-04-17 03:19追記)

お約束通り、EDGE Now!のクローラーがきたので、キャプチャをとってみました。

Edgenowuseragent
▲User-Agentがとれなかったようだ

これはこれでおもしろい結果。アドビともあろう企業が、User-Agent設定せずにクローラ作るわけ無いと思うし、これはどう判断したらいいんだろう。

おととい作ったEDGE Now!外部DBは、EDGE Now!で参加者が紹介してくれたURLを、紹介された順番で登録していますので、それを利用すると、RSSができるのではないかと思いました。

というわけで早速スクリプト。

Filename: index.rdf

#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use DBI;
use LWP::UserAgent;
use URI::Escape;
use XML::Simple;
use XML::RSS;
use utf8;
use Encode;
binmode STDOUT => ':utf8';
 
my $q = CGI->new();
my $result = get_data();
my $rss    = rss($result);
if ($ENV{GATEWAY_INTERFACE}) {
    require CGI;
    print CGI::header('text/xml; charset=utf-8');
}
print $rss;
 
exit;
 
 
sub rss {
  my $items = shift;
  my $rss = XML::RSS->new;
  $rss->add_module(
    prefix => 'content',
    uri    => 'http://purl.org/rss/1.0/modules/content/',
  );
  
  $rss->channel(
    title    => 'EDGE Now! 今注目されているサイト',
    link     => 'http://edgenow.jp/',
    description => 'EDGE Now! 今注目されているサイトのRSS',
    language => 'ja',
    dc => {
      publisher    => 'アドビシステムズ株式会社',
      contributor  => 'DTPWiki.jp',
    },
    syn => {
      updatePeriod    => 'daily',
      updateFrequency => '12',
    },
  );
  
  foreach my $item (@$items) {   
      $rss->add_item(
        link  => $item->{'url'},
        title => _escape( decode('utf8',
                                 $item->{'title'}
        ) ),
        description => _escape(
                         decode('utf8',
                                "$item->{'title'} "
                                ."$item->{url}"
        ) ),
        dc => {
          date => _date( $item->{'ctime'} ),
        },
      );
  }
  return $rss->as_string() ;
}
 
sub get_data {
  my $db_path = 'edgenow_sites.db';
  my $dbh = DBI->connect( "dbi:SQLite:dbname=$db_path",
                          "","", {AutoCommit => 0} );
  my $sth  = $dbh->prepare("SELECT * FROM urls "
                          ."ORDER BY id DESC LIMIT 50");
  my $result = $sth->execute() || die $!;
  my $hash;
  while (my $ref = $sth->fetchrow_hashref) {
    push @$hash, $ref;
  }
  $dbh->commit();
  return $hash;
}
 
sub _date {
  my $date = shift;
  $date =~s/\s/T/g;
  $date .= '+00:00';
  return $date;
}
 
sub _escape {
  my $str =shift;
  $str =~s/&/&amp;/g;
  return $str;
}
 
__END__

これは実際にアクセスできます。

http://labo.dtpwiki.jp/edgenow/index.rdf

だいたいSQLiteのDBの扱い方にも慣れてきましたので、次回は、URLを問い合わせると、紹介した人の人数をEDGE Now!に問い合わせして、User数として返すXML-RPCインターフェースをつけてみようと思います。

昨日EDGE Now!の内部にあるであろうデータベースを外部に設けたわけですが、これを活用するため、まず作ったDBの最新50件を表示する簡単なスクリプトを用意します。

Filename: db.cgi

#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use DBI;
 
my $q = CGI->new();
print $q->header(-type => 'text/plain', -charset =>'UTF-8', );
print <<'END_OF_TEXT';
  id  |       ctime       |  eid |    url    |    title    |
END_OF_TEXT
 
my $dbh = DBI->connect(
  'dbi:SQLite:dbname=edgenow_sites.db',
  undef, undef , {AutoCommit => 0} );
my $sth = $dbh->prepare(
  'SELECT * FROM urls ORDER BY id DESC LIMIT 50'
);
my $res = $sth->execute();
while( my $ref = $sth->fetchrow_hashref ){
  printf(
    "%6d|%-18s|%6d|%s|%s\n",
    $ref->{id},
    $ref->{ctime},
    $ref->{entryid},
    $ref->{url},
    $ref->{title},
  );
}
$dbh->commit;
 exit;
 
__END__

これは実際にアクセスできます。

http://labo.dtpwiki.jp/edgenow/db.cgi

よく見ますと、サイトにはじめて登録された順番に並んでくれています。おお、これ使うと新着RSSできるんじゃね? ていうことで次回このDBを使ってRSSを作ります

おまけ。さっきの表示スクリプト、もっとアジャイルに作りたいというのであれば、sqlite3を使って、こういうのもありかも。

Filename: db2.cgi

#!/usr/bin/perl
use strict;
use warnings;
use CGI;
my $q = CGI->new();
my $res = `sqlite3 edgenow_sites.db 'SELECT * FROM urls ORDER BY id DESC LIMIT 50;'`;
print $q->header(-type => 'text/plain', -charset =>'UTF-8', );
print <<'END_OF_TEXT';
id  |       ctime       |eid |    url    |    title    |
END_OF_TEXT
print $res;
 
exit;
 
__END__

EDGE Now!は、参加者みんなからURLを紹介してもらっているわけですけれども、紹介してもらったURLを一覧するインターフェースがありません。

一見、LATEST SITEの欄に表示されているように見えますが、ここの欄は、午前1時のその日初のクロール直前にリセットされてしまうので、ストックされているわけではないのです。

これをストックしておかないと、特定URLがEDGE Now!にすでに登録されているかどうか分からないので、いろいろおもしろいサービスが作れません。

というわけで、EDGE Now!内部のDBの代わりに、外部でEDGE Now!に新規登録されたサイトをDBに登録してみようと思いました。

Filename: edgenow_sites.db

$ sqlite3 edgenow_sites.db
SQLite version 3.1.2
Enter ".help" for instructions
sqlite> CREATE TABLE urls (
  id      INTEGER PRIMARY KEY AUTOINCREMENT,
  ctime   DEFAULT CURRENT_TIMESTAMP,
  entryid INTEGER,
  url     TEXT,
  title   TEXT,
  option  TEXT
);
sqlite> .schema
CREATE TABLE sqlite_sequence(name,seq);
CREATE TABLE urls (
  id      INTEGER PRIMARY KEY AUTOINCREMENT,
  ctime   DEFAULT CURRENT_TIMESTAMP,
  entryid INTEGER,
  url     TEXT,
  title   TEXT,
  option  TEXT
);
sqlite> .q
$

Filename: robot.pl

#!/usr/bin/perl
use strict;
use warnings;
use DateTime::Format::MySQL;
use DBI;
use LWP::UserAgent;
use URI;
use URI::Escape;
use utf8;
use XML::RSS;
use XML::Simple;
binmode STDOUT => ':utf8';
 
# 定数
our $referer = 'http://labo.dtpwiki.jp/edgenow/index.rdf';
my  $db_path = 'edgenow_sites.db';
 
# LWP::UserAgent 用意
our $ua  = LWP::UserAgent->new;
$ua->timeout(10);
$ua->agent( "EDGENow!index.rdf/0.1($referer)" );
 
# DB 用意
our $dbh = DBI->connect( "dbi:SQLite:dbname=$db_path",
                         q(), q(),
                         { AutoCommit => 0 }
                       );
my $sth  = $dbh->prepare( "INSERT INTO urls "
                         ."(entryid, url, title, option, ctime ) "
                         ."VALUES (?, ?, ?, ?, ?)");
my $sth2 = $dbh->prepare( "SELECT * FROM urls WHERE entryid = ?" );
 
 
# メインルーチン
my $result = get_data(); #EDGE Now!からXMLデータをある分だけ取得
 
# 帰ってきたハッシュを処理。DBと照合してまだ無い項目を追加します
foreach my $id ( sort keys %$result ) {
  my $hash   = $result->{ $id };
  my $result = $sth2->execute( $id ) or die $DBI::errstr;
  my $ref    = $sth2->fetchrow_hashref;
  next if $ref;
  next if ref( $hash ) ne 'HASH';
  next unless $hash->{url}->[0];
  my $title  = ref( $hash->{title }->[0] ) eq 'HASH'
                 ? q()                   # NULLの場合
                 : $hash->{title }->[0]; # NULLでない
  my $option = ref( $hash->{option}->[0] ) eq 'HASH'
                 ? q()                   # NULLの場合
                 : $hash->{option}->[0]; # NULLでない
  my $url    = uri_unescape( $hash->{url}->[0] );
  my $ctime  = _date( $hash->{entryTime}->[0] );
  $sth->execute( $id, $url, $title, $option, $ctime );
  print "INSERT INTO urls "
       ."( entryid, url, title, option, ctime ) "
       ."VALUES ( $id, '$url', '$title', "
       ."'$option', '$ctime' )\n";
}
 
$dbh->commit; # DBコミット
 
exit;
 
 
# EDGE Nowから必要分取得する
sub get_data {
  my $refs = {};
  my $i    = 0;
  my $max;
  while ( 1 ) {
    my $ref = get_EDGENow( $i ); # EDGE Now!からページ
                                 # 指定でハッシュ取得
    $max = $ref->{module}->[1]->{count} if $i == 0; # 項目数
    $refs = { 
              %$refs, 
              %{ $ref->{siteList}->[0]->{site} }
            };                 # ハッシュ合流
    $i++;
    last if ($i * 5 >= $max);  # もうEDGE Now!から取得しなくてよし
  }
  return $refs;
}
 
# EDGE Now!から1ページ分取得する
sub get_EDGENow {
  our ( $ua, $referer );
  my $page  = shift;
  my $proxy = 'http://edgenow.jp/xml/edgeNow.php';
  my $uri   = URI->new( $proxy );
  $uri->query_form( page => $page, ) if $page;
  my $req = HTTP::Request->new( GET => $uri->as_string );
  $req->referer( $referer );
  my $res = $ua ->request( $req );
  my $xml = $res->content;
  my $xs  = XML::Simple->new();
  my $ref = $xs->XMLin( $xml, forcearray => 1 );
  return $ref;
}
 
# EDGE Now!の日付データをMySQL形式に変換
sub _date {
  my $date      = shift;
  my @s         = split( ' ', $date );
  my $timestamp = "$s[0]-$s[1]-$s[2] $s[3]:$s[4]:$s[5]";
  my $dt        = DateTime::Format::MySQL
                  ->parse_datetime( $timestamp )
                    ->set_time_zone( 'local' );
  return DateTime::Format::MySQL
           ->format_datetime( $dt->set_time_zone( 'UTC' ) );
}


実行例:

$ ./robot.pl
INSERT INTO urls ( entryid, url, title, option, ctime ) VALUES ( 5670, 'http://www.suzurankai.com', 'リリー オブ ザ バレイ-サロン ド フルール 少人数制サロンの フラワーアレンジメント教室です。', '', '2008-04-14 14:11:11' )
INSERT INTO urls ( entryid, url, title, option, ctime ) VALUES ( 5671, 'http://30d.jp', '30日間限定オンラインアルバム | 30days Album™', '', '2008-04-14 14:11:11' )
INSERT INTO urls ( entryid, url, title, option, ctime ) VALUES ( 5672, 'http://tha.jp/feed', 'tha feed!', '', '2008-04-14 14:11:14' )
$ 

このrobot.plを、EDGE Now!のクローリング間隔である2時間ごとに回すとOK。

こうやって、DBに登録した奴を利用して、

M.C.P.C.: EDGE Now!のリンク件数を返す野良API(XML-RPC)

にて、URLから、EDGE Now!に紹介した人数が得られるようになっています。次回は、EDGE Now!に紹介した人数が得られるXML-RPCサーバのプログラムを紹介するつもり。

昨日長岡技術科学大学で行われたオープンソースカンファレンス 2008 Nagaokaに行ってきました。

http://www.ospn.jp/osc2008-nagaoka/

長岡技術科学大学の桜の写真
▲長岡技科大は学内桜だらけでいいねー

まあ、講義棟がどこだか分からず奥までいってしまったわけですが。

普段の出張だったらスーツ着用ですが、今回は私用なので私服でいったら見事学生に紛れてよかった(つもり)。

参加したのは、

  • OSS事例紹介「システム会社と二人三脚で段階的にITシステムを強化」
  • Railsで作る社内システム ~ワークフローシステム開発事例紹介~
  • MediaWikiでコミュニケーション
  • データベースをアプリに組み込もう!~実践Firebird / MySQL / SQLite~

の4つ、あと閉会式&抽選会。

んで、情報系の大学に入ったつもりだったのに講義が顎関節とか機能的電気刺激とかサイバーパンクあふれる講義ばかりでドロップアウトしてしまった僕にとっては、ふつーにソフトウェア関連の発表を見るのは新鮮でした。

参考になったのは最後のセミナーかな。SQLiteでいいんだっていう自信になったw

Nagaokautdb
▲こういうプロダクト別比較表って助かるよね

このセミナーの開催を教えてくれたS君ありがとう。

※抽選会で景品当たらなかった。ちえっ。

誰も長岡のこと教えてくれなかったので、
PSPとみんなの地図2(GPS同梱)かったぞバーロー

ちなみに買ってからみんなの地図3が近々でること知ったぞ

どうしてくれる

野良RSSフィードを生成したいと思うのは、たいてい情報発生元のWebがRSSフィードを発行していなくて不便だなーと感じる場合であり、そうなると野良RSSフィードの内容は、生成スクリプトを書いた人の好みに合わせられます。

たとえば、僕が野良RSSフィードを作ると、RSS 1.0に準拠して、description要素の中は要約ということで元ページのHTMLタグを除去した全文、content:encoded要素の中身は、元ページのHTMLのママ、という風にします。

そうやって野良RSSを作っていたのですが、ある日情報発生元のWebがリニューアルし、RSSフィードを自前で発行するということになりました。これはめでたい!ていうのと、今まで勝手にスクレーピングしてすまんかった、という気持ちとで、野良RSSフィードのURLでアクセスしてきたら、本家のRSSフィードに301リダイレクトをかける設定にしました。

ところが、そのリダイレクト先のRSSフィードは野良RSSフィードよりもスペックが劣っていることが往々にしてあります。元々、野良RSSを作ったときは、オレオレ仕様だったわけですが、本家の設置者は「RSSフィードは全文配信はけしからん!」ていう考えかもしれんし、RSSフィードが勝手に出るシステムにしただけで「らっき☆」とかいっているだけかもしれんし。

そういうとき、野良RSSフィード作っていた人は、どうするべきなんだろう。野良だけに本家の意思を尊重しなくてもいいっていうのが正解でしょうけど、せっかくできた本家のRSSフィードが使いにくい、というのを伝える機会もほしいよね。

とにかくいえるのは、本家がRSSフィードを発行するようになったからと言って、たいてい野良RSSとすりあわせがされているわけではないので、油断はできないってことです。

土曜日にちょっと長岡技科大に用事が出来たんで行ってくるんですけれども、長岡技科大はおろか長岡って行ったことなんです。あそこって、駐車場とかあるんですかね。

その前に会場に着けるかどうか不安です……

あと京都の人って長岡京のことを長岡って言いよるよね。土地柄を感じるよね。

OCRも結構進化しましたよね。でも、キヤノンはJAGATにFAXでプレスリリースを送ってきて、それをOCRしたってことなのか。って思わせる出来事、Print-Betterにこんなのがありました。

キヤン/PosterArtist次期パージョンの繰り上げ発売につい [www.print-better.ne.jp]

Kiyans
▲CanCamでもないし、キョンでもない

キョンと言えばハルヒだが、ハルヒと言えば涼宮ではなくて神坂春姫っていうことでひとつ。

ドワンゴ、美少女ゲームの世界を再現した3D仮想空間を今夏開始 [internet.watch.impress.co.jp]

 アイスペースでは、「CLANNAD」「SHUFFLE!」「D.C.II ~ダ・カーポII~」といったゲームの世界を3D空間で再現する。各世界を結ぶ街として、東京・秋葉原をモデルにした「アキハバラ島(仮)」も用意する。

 ユーザーには、自分の分身となる主人公アバターと、ゲームキャラクターのアバター「キャラドル」が与えられる。キャラドルとの会話や着せ替え、動きの設定などが可能になる予定で、キャラクターを自分好みにカスタマイズしていく“育成”要素も盛り込まれている。

これはエロイ

僕はこの仮想空間でどんな商売が展開されるか期待大です!(曲芸商法的な意味で)

ISOカラーチャートのおねえさん そういうこともあるだろう/ウェブリブログ [hobby-dialy.at.webry.info]

このおねえさんの正体は「じゃ」の人が語っていたのどっかで見た。

PS3専用ソフト「メガゾーン23青いガーランド」、値段がこなれてきた頃を見計らって、買ってきました。

僕が買ったのは、海外版PART2が特典としてつく

  • : メガゾーン23 青いガーランド LIMITED EDITION

    メガゾーン23 青いガーランド LIMITED EDITION

  • ではなく、

  • : メガゾーン23 青いガーランド-通常版

    メガゾーン23 青いガーランド-通常版

  • です。現時点でAmazonでの値段は3308円(54%OFF)!そして、レビューキツスw

    PS2の性能で十分なことをPS3でやるところがいいですね。あと、バイク乗るところで画面がバイクの振動に合わせてスクロールするのですがその処理がずさんで88SRソーサリアンで言うところのテキストで黒マスクしなきゃいけないところがマスクされてないのではみ出ていてすごいやばい。コンパイルの名前を引き継いだメーカー製のソフトとしてはスクロールに関してこれはいかがなものかと思いました。

    そんで、アドベンチャーゲームなのにメッセージ読み戻しできないの。制作者は、ToHeart2 Another Dasyとかをプレイしてシステムを検討してほしかった。

    時祭イブが20年もテレビに第一線で出ている時点で気付って思いました。「最近のイブは軍隊の服ばかり着て」みたいな発言あったけど、その発言したキャラクターが小さいときから軍の服を着ているはずなんだけどね。

    ちなみに僕が買った理由はわくわくさんです。

    昨日のEDGE Now!登録ブロガーにリンクされたサイトURLからリンクユーザ数を得る野良APIを実際に使ってみる例です。

    やっぱりはてなのまねですw


    複数のURLに対するリンク数を出力するPerlサンプルスクリプトは以下のようになります。ここでは XML-RPC の処理に XMLRPC::Lite モジュールを利用しています。

    #!/usr/bin/perl
    use strict;
    use warnings;
    use XMLRPC::Lite;
                                                   
    our $EndPoint = 'http://labo.dtpwiki.jp/edgenow/xmlrpc.cgi';
                
    my @urls = (                           
        'http://www.chanel-mobileart.com/',
        'http://blog.lv99.com/?eid=774586',                     
        'http://tokyo.interactive.ad.awards.jp/Results08/list.html',
    );
                          
    my $map = XMLRPC::Lite                                      
         -> proxy($EndPoint)
         -> call ('link.getCount', @urls)
         -> result;
     
    printf("%d\t%s\n", $map->{$_}, $_) for @urls;

    上記スクリプトをコマンドラインから実行した場合、以下の様な結果が得られます。

    $ perl client.pl 
    5       http://www.chanel-mobileart.com/
    1       http://blog.lv99.com/?eid=774586
    5       http://tokyo.interactive.ad.awards.jp/Results08/list.html

    実際の実装例は、

    各SBMサービス別オンラインブックマーク件数チェック

    になります。

    EDGE Now!では、特定のURLを紹介した人が見られるようになっていますが、これって、SBMと同じなんですよね。つうわけで、あるURLを紹介した人の数を取得できると便利だと思ったんですけれども、EDGE Now!の外部に露出しているところにそのようなAPIはない。

    ということで、野良APIを作ってみました。

    はてなブックマーク件数取得APIとは - はてなダイアリー [d.hatena.ne.jp] に合わせました。


    EDGE Now!で紹介されたURLに対し、紹介した人の数を返します。EDGE Now!の仕様で、0~5までしか返ってきませんw
    メソッド名および指定可能な各属性は、以下の通り。

    uri
    http://labo.dtpwiki.jp/edgenow/xmlrpc.cgi
    methodName
    link.getCount
    parameters
    件数を取得したいURLを指定(複数指定可能)

    内部でEDGE Now!のAPIたたいていますので、あんまりいっぱい指定しても駄目。
    あと、EDGE Now!が始まった頃からの4000エントリは、残念ながら数値が出ませんw

    今回XML-RPCサーバを作るに当たって、自分のblogの過去のエントリ
    M.C.P.C.: XMLRPC::LiteでHello, World!を再利用して作りましたとさ。

    呼び出しサンプルは次のエントリで(せこいなー)

    hetemlのお試しを使っていて、ちょっとXMLRPC::Lite使おうと思ってプログラム作ってFTP転送したら、

    Software error:
    Can't locate XMLRPC/Lite.pm in @INC (@INC contains:
    /usr/lib/perl5/5.8.5/i386-linux-thread-multi
    /usr/lib/perl5/5.8.5
    /usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.4/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.3/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.2/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.1/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.5
    /usr/lib/perl5/site_perl/5.8.4
    /usr/lib/perl5/site_perl/5.8.3
    /usr/lib/perl5/site_perl/5.8.2
    /usr/lib/perl5/site_perl/5.8.1
    /usr/lib/perl5/site_perl/5.8.0
    /usr/lib/perl5/site_perl
    /usr/lib/perl5/vendor_perl/5.8.5/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.4/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.3/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.2/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.1/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.5
    /usr/lib/perl5/vendor_perl/5.8.4
    /usr/lib/perl5/vendor_perl/5.8.3
    /usr/lib/perl5/vendor_perl/5.8.2
    /usr/lib/perl5/vendor_perl/5.8.1
    /usr/lib/perl5/vendor_perl/5.8.0
    /usr/lib/perl5/vendor_perl .) at test.cgi line 30.
    BEGIN failed--compilation aborted at test.cgi line 30.
     
    For help, please send mail to the webmaster (admin@heteml.jp), giving this error message and the time and date of the error.

    とかでました。

    おそらく perl -MCPAN -e shell は使えないんだろうなあ。さくらインターネットの方がシェル使えるし、そっちにしようかな。

    (2008-4-3 17.15変更)このエントリを挙げるにあたっての手続きに不備がありましたので、全文削除しました。

    CoCoLo

    | コメント(0) | トラックバック(0)

    Filename: cocolo.js

    #!/usr/bin/perl
    use strict;
    use warnings;
    use LWP::UserAgent;
    use CGI;
     
    my $q = CGI->new();
    my $referer = $q->referer() || 'http://blog.dtpwiki.jp/';
    my $cocolo_url = 'http://www.blogpet.net/js/641d076399ee15a6a5aaa64eb6d75acc.js';
     
    my $js = get_blogbet_js( $cocolo_url, $referer, );
    $js =~ s/this.width = 130/this.width = 469/;
    $js =~ s/this.height = 220/this.height = 794/;
    print $q->header( -type => 'text/javascript' );
    print $js;
     
    exit;
     
    sub get_blogbet_js {
      my $url     = shift;
      my $referer = shift;
      my $ua      = LWP::UserAgent->new();
      $ua->agent('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)');
      my $req = HTTP::Request->new(
        'GET',
        $url,
      );
      $req->referer( $referer );
      my $res = $ua->request($req);
      my $content = $res->content;
      return $content;
    }

    一年の計は元旦にありっていうけれども、年度の計は4/1にやってもいいよね、本当になるかどうかは知らん。

    今年度は

    印刷屋さんとして、オンラインサービスを公開したいな。言うだけだったらタダだもんね。

    月別 アーカイブ

    ウェブページ

    OpenID対応しています OpenIDについて
    Powered by Movable Type 5.2.13

    このアーカイブについて

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

    前のアーカイブは2008年3月です。

    次のアーカイブは2008年5月です。

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