to be continued ~とあるプログラマーの実験的開発日誌~ -18ページ目

to be continued ~とあるプログラマーの実験的開発日誌~

WEBデザイナー兼プログラマーである管理人が日々のトラブル解決に向けて奮闘する開発日誌。

WEB開発で頭を悩ませる問題のひとつが、文字コードの違いによるトラブルだ。とくにPerlなどで書かれたスクリプトはスクリプト自体が書かれた文字コード、そのスクリプトが対象としている文字コード、さらに出力されるHTMLなどの文字コードと、非常に複雑になっている。コードを確認しようとしたものの、文字化けで読めないなどということも珍しくはない。


そうした中で、経験上もっとも優秀なテキストエディタと感じたのが、今回紹介する「TeraPad」だ。定番ソフトとしてご存知の人も多いだろうが、実際他のテキストエディタでは文字コードを変更しても直らないような場合でも、TeraPadなら正常に読めるということが何度もあったので、改めてその性能を実感させられたことからやはり外せない必須ソフトとなっている。


このエディタひとつあれば、簡単なメモの作成から本格的なHTMLの記述、Perlの開発まで、様々なことに対応できる。それだけにその良さは文章では紹介しづらい。実際に使ってみることで良さがわかるソフトの代表格といえるだろう。


公式サイト:ToClip for Windows





Perlを記述していると、取得したHTMLなどからURLや特定のファイルだけを抜き出したいという場合がよくある。難しい処理ではないのだが、そのたびにいちいち思い出しながら書くのは面倒なので、定型として備忘録的にメモしておく。


■URLからファイル名を抽出


my $url = "リンク先の画像などのアドレス";
my $pos = rindex($url,"/");
#URLの最後尾の"/"を取得(rindex=最後から対象文字を検索して位置を返す)
my $file_name = substr($url,$pos+1);
#最後尾の"/"以降がファイル名になるので、"/"の次の文字から最後の文字までを抜き出す


■ついでに抜き出したファイルの拡張子を抽出


上記のスクリプトに続いて以下を記述


($name,$file) = split(/\./, $file_name);
#抜き出したファイル名を"."で分離して、それぞれを格納。拡張子は当然$fileに入っている。


■HTMLなどから特定のタグ要素を抽出(例は画像タグをすべて抽出している)


my $html = "LWPなどで取得されたHTMLが格納されていると仮定";
my $match = "img src=";
my ($pos1,$pos2,$pos3);
my $int = 0;
while(1) #ループ指定
{
$pos1 = index($html,"$match",$int); #$intの位置からマッチする位置を検索
if ($pos1 != -1) #マッチした場合
{
$pos2 = index($html,">",$pos1); #pos1を開始位置にタグの最後の位置を検索
if ($pos2 != -1) #マッチした場合
{
@img_tag = substr($html,$pos1-1,$pos2-$pos1+2); #タグの先頭位置からタグの長さ分を抜き出す
}
$int = $pos1+1; #新たな開始位置に前回のマッチした次の文字を指定して繰り返す
}
else
{
last;
#$pos1が-1ということはもうマッチするタグがないということなので、ループを抜けて終了する
}
}


「{}」の書き方が普通と違うのは癖です。見づらかったらすみません。


PerlライブラリであるImage::SizeとLWPを組み合わせて、リンク先(外部サイトにある)の画像サイズを取得するためのTips。RSSリーダーを自作するに当たって、本文中の絵文字とアップされた画像を区別するために必要となった。当然ながら利用するにはcgiサーバにどちらもインストールされていることが条件となる(ちなみに自作したRSSリーダーは上部ナビの「公式サイト」のトップページに表示されているので興味がある方は覗いて見て欲しい)。


まずはImage::Sizeだが、これは画像サイズを取得するためのライブラリ。使い方は簡単で、以下のようにスクリプトに記述する。


use Image::Size;
($width, $height) = imgsize("取得したい画像のパス");


これで $widthと$heightには、それぞれ画像の幅と高さが格納されている(変数の値を調べるには、以前に紹介した「CGI-Perl開発におけるデバッグのTips」を参考にしてみて欲しい)。


ただし、これで取得できる画像は同じサーバ内のものに限られるため、リンク先などの外部にある画像サイズを取得するには、別に画像を取得してやる必要がある。そのために利用するのが、Perl 用のWWWライブラリモジュール群であるLWPだ。LWPで外部から画像を取得する方法は、以下の2つ。


LWP::Simpleを利用する場合、次のように記述する。


use LWP::Simple;
$url = '取得したい画像アドレス';
$get_img= get $url;


出力される結果はテキスト形式なので、意味不明の文字が並ぶがサイズを取得する上では問題ない。あとは$get_imgをImage::Sizeに受け渡せば良い。


私の環境下ではこの方法で問題なく取得できたのだが、一部にLWP::Simpleでは取得できないページがあるというような報告があったので、 別の方法も合わせて紹介する。LWP::Simpleで取得できない理由は、User-Agentリクエストヘッダがないことが原因のようなので、WP::UserAgentを利用する。


use LWP::UserAgent;
$ua = LWP::UserAgent->new;
$req = HTTP::Request->new(GET => "取得したい画像アドレス");
$res = $ua->request($req);
$get_img = $res->content;


あとはLWP::Simpleと同じである。


ついでに私はPerlのローカルテスト環境にAN HTTPD+ActivePerlをメインに利用しているのだが、デフォルトのActivePerlにはImage::Sizeがインストールされていなかったので、その方法を紹介しておく。


コマンドプロンプトから以下のように記述。


C:\Documents and Settings\user名> ppm install image::size


(C:\perl\にActivePerlがインストールされている場合。ppmはPerlのパッケージマネージャー)


最近、自作していたウェブ型RSSリーダーが一応完成したので、これを利用した新サイトを立ち上げた。様々なRSSを収集してカテゴリー別にわけて、まとめて読もうというサイトだ。


目玉は今をときめくAKB48メンバーの公式ブログをまとめて閲覧できること。30以上ある公式ブログを一つ一つ見て廻るのは大変だろうと思い、一度に読めるようにした。当然、記事内からそれぞれのブログへのリンクも貼っているので、気になる内容があればそのページに移動すればいいし、ざっと見るだけなら手間はかからない。できれば総選挙に間に合わせたかったが残念・・・。


今後は姉妹グループのブログなども読めるようにしていこうと考えているので、興味がある方は覗いてみて欲しい。


リンク先:RSS情報局


ホームページ上でCGIなどを使用していると画面が表示されるまでに結構時間がかかる。私自身もそうだが、訪問者というのはせっかちなもので、真っ白な画面をいつまでも眺めていてはくれない。とはいえ、わざわざFlashでローディング画面を自作するのも面倒だ。


そこでJavaScriptで簡単に読み込み中であることを訪問者に知らせるTipsを調べてみた。


<<< JavaScript >>>


<script language="JavaScript"><!--
function loading(){
document.getElementById("読み込み中に表示させたいブロック要素のID").style.display= "none";
document.getElementById("読み込んだ後のブロック要素のID").style.display= "block";
}
onload=loading;
// -->
</script>


<<< HTML >>>


<div id="読み込み中に表示させたいブロック要素のID">
ここにローディング中に表示させたい内容を記述する。テキストでも画像でもOK。noscriptタグを使えばJavaScriptが無効になっている訪問者に注意喚起もできる。
</div>


<<< CSS >>>


#読み込み中に表示させたいブロック要素のID {
position:absolute;
text-align:center;
font-size:100%;
width:100%;
height: 100%;
background: #FFF;
padding-top: 200px;
z-index:2;
}


要するにJavaScriptでローディング中は「読み込み中に表示させたいブロック要素のID」を持つブロックを表示させておき、読み込みが終わったら、display= "none"で隠すというわけだ(そのためJavaScriptが無効になっているとローディング表示が消えないので注意が必要)。 本来、表示させるべきページ全体も<div>などのブロック要素で囲っておく。


ポイントはスタイルシートの記述で、JavaScript自体では読み込み中の画面を隠してはいない。従って、そのままではローディング画面と本来のページが重なってしまうのをCSSでローディング画面の幅、高さを100%にして背景色を指定し、 z-indexで他の要素より前に表示させるようにして擬似的に本来のページを見えなくしている。それにより、訪問者にはローディング画面から本来のページに瞬時に切り替わったように見えるわけだ。