Translate

2009年6月29日月曜日

SPIDERING HACKS(#14)

#14は、相対URLを絶対URLに直しちゃうってお話ですね。
どうやら、URIモジュールのnew_absってメソッドに
相対URLとBaseURLを渡すと絶対URLを返してくれますよん。
ってことなんだって。

じゃ、BaseURLをどうしてゲットすりゃいいのかって話になると
LWP::UserAgentオブジェクトでgetとかpostした後でbaseメソッドで
取り出せるんですね。

ここいらの話を使ってコードを書いてみるとこんな感じ。
#!/usr/bin/perl#!/usr/bin/perl                                                                                     
use strict;
use warnings;
use URI;
use LWP;

#適当に階層の深そうなアドレスを用意してみる。
my $uri = URI->new('http://search.cpan.org/~gaas/URI-1.38/URI.pm');
my $UA = LWP::UserAgent->new();
my $response = $UA->get($uri);

#下記相対URLを絶対URLに直してみる。
my @list = qw(./1.html ./../2.html ./../../3.html ./hoge/0.html);

for my $list (@list){
print URI->new_abs($list, $response->base), "\n";
}


実行してみるとこうなる。
http://search.cpan.org/~gaas/URI-1.38/1.html
http://search.cpan.org/~gaas/2.html
http://search.cpan.org/3.html
http://search.cpan.org/~gaas/URI-1.38/hoge/0.html


なるほろね。
おまけ。
URIモジュールといえば、アドレスを分解するのに
非常に便利いいのでここにのっけておく。。
#!/usr/bin/perl#!/usr/bin/perl                                                                                     
use strict;
use warnings;
use URI;

my $u = URI->new('http://www.cpan.org/authors/00whois.html#hogehoge');

print "scheme:", $u->scheme, "\n";
print "opaque:", $u->opaque, "\n";
print "path:", $u->path, "\n";
print "frag:", $u->fragment, "\n";
print "host:", $u->host, "\n";


実行結果は
scheme:http
opaque://www.cpan.org/authors/00whois.html
path:/authors/00whois.html
frag:hogehoge
host:www.cpan.org

2009年6月28日日曜日

SPIDERING HACKS(#12)

formのメソッドタイプがGetの場合はURIモジュールのquery_formメソッドを
使うと便利よいよって話なので、それを使ってなにか書いてみる。

例)知恵袋にクエリーを送ってヒットした件数を抜き出す。
文字コード:utf8
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use URI;
use LWP;
use Encode qw(decode_utf8 encode_utf8);

my $search_word = decode_utf8(shift);
my $browser = LWP::UserAgent->new();
my $uri = URI->new('http://search.chiebukuro.yahoo.co.jp/search/search.php');
$uri->query_form(
flg => 3,
fr => 'chie-search-t',
p => encode_utf8($search_word),
);

my $res = $browser->get($uri);
if(decode_utf8($res->content) =~ m/([\d,]+件)/){
print encode_utf8($1), "\n";
}else{
print encode_utf8('Yahoo!知恵袋で、条件に一致する質問はみつかりませんでした。'), "\n";
}


utf8フラグ付きの鉄則は、スクリプトが受け取る時にdecode(もらうデータの文字コード, '文字列');
自分の書いたスクリプトを離れる時(printする場合や、モジュールに渡す場合などなど)に
encode('渡す先の文字コード', '文字列')
とすればよいっと。
あらかじめutf8に変換するってのがわかっている時は
use Encode qw(decode_utf8 encode_utf8);
のようにutf8用の関数を呼び出すとちょいとコードを書くのが楽になったりするわけね。

というわけで中身のメモ。
1行目 シェバン。(perlのありかを指定)
2行目〜7行目 モジュールの呼び出し
9行目 データの受け取りなのでさっそくdecode_utf8してフラグをつける。
   ※スクリプト実行時の引数がutf8で渡されることを前提としている。
10行目 LWP::UserAgentオブジェクトの生成。
11行目 知恵袋のsearchアドレス
12行目 パラメの組み立て作業。
URIオブジェクトのquery_formメソッドにハッシュで渡せばOK
URIへのエンコードも行ってくれる。
15行目 URIオブジェクトに渡すんでフラグを取る。
知恵袋がUTF8なんでutf8でエンコードする。
18行目 getしてデータを受け取る。contentプロパティにリクエストが格納される。
19行目以下。
データを受け取ったんでdecodeしてフラグをつける。
ヒット件数の部位を正規表現でヒットしたらその件数をprintするか
しなければ、ヒットしなかった趣旨を表示して終了。

formのメソッドがpostの時は下記の感じになる。。
文字コード:utf8
#!/us/bin/perl                                                                                     
use strict;
use warnings;
use utf8;
use LWP;
use Encode qw(decode_utf8 encode_utf8);

my $pref = decode_utf8(shift);
my $address = decode_utf8(shift);
my %pref = (
'北海道'=>1, '青森県'=>2, '岩手県'=>3, '宮城県'=>4, '秋田県'=>5,
'山形県'=>6, '福島県'=>7, '茨城県'=>8, '栃木県'=>9, '群馬県'=>10,
'埼玉県'=>11, '千葉県'=>12, '東京都'=>13, '神奈川県'=>14,'新潟県'=>15,
'富山県'=>16, '石川県'=>17, '福井県'=>18, '山梨県'=>19, '長野県'=>20,
'岐阜県'=>21, '静岡県'=>22, '愛知県'=>23, '三重県'=>24, '滋賀県'=>25,
'京都府'=>26, '大阪府'=>27, '兵庫県'=>28, '奈良県'=>29, '和歌山県'=>30,
'鳥取県'=>31, '島根県'=>32, '岡山県'=>33, '広島県'=>34, '山口県'=>35,
'徳島県'=>36, '香川県'=>37, '愛媛県'=>38, '高知県'=>39, '福岡県'=>40,
'佐賀県'=>41, '長崎県'=>42, '熊本県'=>43, '大分県'=>44, '宮崎県'=>45,
'鹿児島県'=>46, '沖縄県'=>47,
);

my @error;
push @error, encode_utf8("その都道府県は存在しません!\n") if(!exists $pref{$pref});
push @error, encode_utf8("引数が足りません。都道府県と市区町村名を渡して下さい\n")
if(!defined $address);
die print @error, "\n" if(@error);

my $browser = LWP::UserAgent->new();
my $uri = 'http://www.post.japanpost.jp/cgi-zip/zipcode.php';
my $response = $browser->post( $uri,
[
pref => $pref{$pref},
addr => encode_utf8($address),
]
);
die "{$uri}エラー:", $response->status_line unless $response->is_success;
print $response->content, "\n";

スクリプト実行時に都道府県名と市区町村・町名を引数に渡せばOK

この項目での肝はgetの時が
LWP::UserAgentを作ったのち
getメソッドなら
$obj->get('URI', %header); #パラメータはURIモジュール等で先に組み立てておく。
postメソッドなら
$obj->post('URI', [key1=>value1, key2=>value2,...], %header);
で取得が可能というお話ですね。

SPIDERING HACKS(#10)

この項目では、LWP::Simpleでは要求したアドレスからただデータを受け取るだけ
なのに対し、クッキーや認証、要求が成立したのか、駄目だったのかを知るには
LWP::UserAgentでよりブラウザ的な振る舞いをさせるための設定を施し、結果を
HTTP::Response周りの関数で調べましょうね。
ってお話ですね。

ここでは、HTTP::Responseオブジェクトのis_successメソッドで
リクエストの可否を調べれることやリクエストが失敗した場合
status_lineメソッドに情報を取り出せること。
MIMEコンテンツ情報は、content_typeメソッドで調べられますよん
って話ですね。

詳細は、
LWP::UserAgent
とか
HTTP::Response
で、調べると良さそうですね。

2009年6月21日日曜日

SPIDERING HACKS(#9)

SPIDERING HACKSのめも。
やっぱり、この手の物は自分のコーディングの
仕方で書いてみるにこしたこたーないしね。

#9 LWP::Simpleを用いた簡単なデータ取得。
自分なりに書いてみた。

文字コードはutf8で書いてます。
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use LWP::Simple;
use Encode;

my $id = shift || '074'; #デフォルトはNz
die "数字を入力して下さい" if ($id !~ m/\d+/);

#外務省海外安全ホームページ
my $url = "http://www.anzen.mofa.go.jp/info/info4.asp?id=$id";
my $content = decode('shiftjis', get($url));
die "{$url}を読込めませんでした。" unless defined $content;

#$contentの中身を解析。
$content =~ s/<!--(.*?)-->//gs;
$content =~ / SELECTED>▼([^<]+)</;
print encode("utf8", "$1\n");
if($content =~ /現在、危険情報は/){
print encode("utf8", "現在、危険情報は出ていません。\n");
}else{
print encode('utf8', "詳細をhttp://www.anzen.mofa.go.jp/で確認して下さい!\n");
}


4行目でuse utf8;をしてマルチバイト文字列はフラグ扱いしています。

8行目メモ。
フラグ付きのコードを書く時って、通常外からデータが来たら
フラグをつけて、出ていく直前にフラグを取るのが鉄則だったり
するけども、8行目のIDについては数字(非マルチバイト)を扱うので
フラグをつけようとしてません。。

13行目メモ。
海外安全ホームページの文字コードはshiftjisなのでフラグ付きにする際に
decode('shiftjis', get($url))で“shiftjisですよ”と教えてあげる。

14行目メモ。
die "{$url}を読込めませんでした。" unless defined $content;

{$url}←これ。
フラグ付きコード特有のあれです。
フラグ付きにすると、マルチバイト文字列をも変数にすることができます。
my $日本語 = "あいうえお";
すら扱うことができます。
つまり、"$urlを読込めませんでした。"ってすると$urlからでした。までが
変数扱いを受けてGlobalだyo!っておこられます。
なので、中括弧でかこって、{$url}とすることで変数がどこまでか明確化するか
$url を読・・・のように半角スペースを入れて変数を区切る必要がありますね。

19,21,23行目
フラグ付きの鉄則として外に出す前にエンコードってことで
エンコードしてます。本コードがutf8で書いているので
エンコードする際には、utf8にしてね。としています。

以上!

2009年6月7日日曜日

CGI::Session

ちょいとメモ。
あちこち眺めつつ、サンプルをまねて.plで実行したら
セッション情報の書き込まれたファイルが生成されるのに
対し、.cgiでローカル環境で動かしてみたらファイルが
生成されないのは、なんで??
レンタル鯖にアップしてみたら普通に生成されてるし。。
うーん。

こういうもんなの??

2009年6月3日水曜日

diredモードのメモ

・diredモード
  → C-x + D

・directoryの作成
  → + (ディレクトリ名)

・directory/fileの削除(Delete)
  → 削除したい(directory|file)にカーソルを合わせ(大文字)D

・ファイル名を変更する(Rename)
  →(大文字) R

・表示内容を更新する
  → (小文字) g