※このサンプルの解説は、「CGI(Perl)の解説」をすべて読み終えてる方を前提としています。
■ PerlでWEBページのソースを表示する
PerlでWEBページのソースを取得するにはHTTPプロトコルを知らなければなりません。
HTTPプロトコルとはみなさんがブラウザの「アドレス」欄に//から始まる、俗に言うURLを入力しますよね。
そうすると、ブラウザが裏側で勝手に処理してくれて、そのページを表示してくれます。
この、裏側で勝手に処理する手順(やり取り)のことです。
これと同じことを相手のサーバーに対し、Perlで行えば、相手のサーバーからWEBページの情報が流れてくるので、それを受け取って表示すればいいのです。
- 【 解 説 】
-
例えば、取得したいページが「//www.aaa.com/bbb.html」だったとします。
このページの情報が欲しい場合、HTTPプロトコルでは、相手のサーバーに対し次のような情報を送信します。
GET /bbb.html HTTP/1.0\r\n Host:www.aaa.com\r\n Connection:close\r\n \r\nさて、この情報を相手のサーバーに伝えるためにはどうすればいいのでしょうか?
まず、相手のサーバーと接続しないといけませんが、Perlの場合、socket(ソケット)関数を使用して相手のサーバーとやり取りをします。
今回、HTTPプロトコルということで、相手のサーバーと接続する手順をPerlで記述すると次のようになります。
use Socket; $port0 = getservbyname('http', 'tcp'); $host0 = 'www.aaa.com'; $ipaddr = inet_aton($host0) or die "ホスト名検出エラー($host)\n"; $sock_addr = pack_sockaddr_in($port0, $ipaddr); socket(SOCK, PF_INET, SOCK_STREAM, 0) or die "ソケット作成エラー($ipaddr / $port0)\n"; connect(SOCK, $sock_addr) or die "サーバー接続エラー($ipaddr / $port0)\n";また、終了手続き(サーバーとの切断)は次のように記述します。
close SOCK;サーバーページの情報が流れてきた場合、次のような手順でデータを取得し、print命令で表示してやります。
while(<SOCK>){ print $_; } ただ、このままだと、WEBページのソースとは関係ないHTTPプロトコルのレスポンスヘッダ(送信データの情報のようなもの)まで表示されてしまうので、前もってこのレスポンスヘッダを取り除く処理を次のように追加しておきます。 while(<SOCK>){ last if m/^\r\n$/; }また、受け取るデータがHTMLタグなのでそのまま表示すると相手のページが表示されるだけになります。
ソースコード表示をするためにタグの無効化と、改行をHTML形式のタグに変換する次のような記述が必要になります。
while(s/</</is){ }; while(s/>/>/is){ }; while(s/\r\n|\r|\n/<br>/is){ };さらに、socket関数を使用してデーターを取得する場合、標準設定では、バッファリングが行われるためいつまでたっても表示されません。
※バッファリングとは、そのつど処理をするのではなくメモリなどに一時的に溜め込んでおいて、指示があった場合などにまとめてデータ処理を行うような仕組みを言います。
このバッファリングを無効にするため、次のような記述も必要になります。
select(SOCK); $|=1; select(STDOUT);
では、上記の内容を手順に従い組み立ててみます。
ファイル名は「webpsrc.cgi」にしてください。
- 【記述サンプル】
- #!/usr/bin/perl -w use Socket; print << "END_OF_DOC"; Content-type:text/html\n\n END_OF_DOC $host0 = "www.yahoo.co.jp"; $port0 = getservbyname("http", "tcp"); $ipaddr = inet_aton($host0) or print "ホスト名検出エラー($host0)<br>\n"; $sock_addr = pack_sockaddr_in($port0, $ipaddr); socket(SOCK, PF_INET, SOCK_STREAM, 0) or print "ソケット作成エラー($ipaddr / $port0)<br>\n"; connect(SOCK, $sock_addr) or print "サーバー接続エラー($ipaddr / $port0)<br>\n"; select(SOCK); $|=1; select(STDOUT); print SOCK << "END_OF_DOC"; GET /index.html HTTP/1.0 Host:$host0 Connection:close END_OF_DOC while(<SOCK>){ last if m/^\r\n$/; } while(<SOCK>){ while(s/</</is){ }; while(s/>/>/is){ }; while(s/\r\n|\r|\n/<br>/is){ }; print $_; } close SOCK;