13 June 2011

(Perl) HTML::Parserを使ってWebページのタイトルを取得する

任意のWebページから、HTML::Parserを使ってWebページのタイトルを取得(抽出)する方法

緑色 : HTML::Parser で HTMLを解析する処理
青色 : LWP::UserAgent と HTTP::Request でWebページをダウンロードする処理

#!/usr/bin/perl use warnings; use strict; use utf8; use HTML::Parser; use LWP::UserAgent; use HTTP::Request; use Encode; binmode(STDIN, ":utf8"); binmode(STDOUT, ":utf8"); my $flag_in_title = 0; # <title>タグと</title>タグの間にあるとき 1 をセット my $str_title; # 抽出された title 文字列 my $enc; # meta http-equiv タグで指定されたエンコード形式 print "title属性を抜き出します\n"; main(); exit; sub main{ # 指定されたURLよりHTMLファイルをダウンロードし $html 変数に格納する print("解析するURLを入力 : "); # 例:http://www.google.com my $url = <>; chomp($url); if($url eq '' or $url !~ /^http:\/\//){ print("Error : 入力が無かった、又はurlが「http://」で始まっていない\n"); exit; } my $req = HTTP::Request->new(GET => "$url"); my $ua = LWP::UserAgent->new; # $ua->proxy('http', 'http://proxy:8080'); my $res = $ua->request($req); if (!$res->is_success){ print("Error : 指定したURLからファイルをダウンロードできない\n"); exit; } my $html = $res->content; # HTML形式の文字列を解析して、title属性を抜き出す my $parser = HTML::Parser->new( api_version => 3, start_h => [\&sub_start_callback, "self, tagname, attr"], # 開始タグ end_h => [\&sub_end_callback, "self, tagname"], # 終了タグ text_h => [\&sub_text_callback, "dtext"], # タグ間の文字列 marked_sections => 1); $parser->parse($html); # 画面表示 if(defined($enc)){ print("encode detected : ".$enc."\n"); if(defined($str_title)){ $str_title = Encode::decode($enc, $str_title); } } if(defined($str_title)){ print("title : ".$str_title."\n"); } } # 開始タグ検出時(HTML::Parserコールバック サブルーチン) sub sub_start_callback{ my ($self, $tagname, $attr) = @_; ## コンストラクタで指定した変数が渡される if($tagname eq 'title'){ $flag_in_title = 1; } if($tagname eq 'meta' and defined($attr->{'http-equiv'}) and lc($attr->{'http-equiv'}) eq 'content-type' and defined($attr->{'content'})){ if(lc($attr->{'content'}) =~ m/utf-8/){ $enc = 'utf8'; } if(lc($attr->{'content'}) =~ m/shift_jis/){ $enc = 'shiftjis'; } if(lc($attr->{'content'}) =~ m/euc-jp/){ $enc = 'euc-jp'; } if(lc($attr->{'content'}) =~ m/iso-2022-jp/){ $enc = 'iso-2022-jp'; } } } # 終了タグ検出時(HTML::Parserコールバック サブルーチン) sub sub_end_callback{ my ($self, $tagname) = @_; ## コンストラクタで指定した変数が渡される if($tagname eq 'title'){ $flag_in_title = 0; } } # タグ間文字列検出時(HTML::Parserコールバック サブルーチン) sub sub_text_callback{ my @dtext = @_; ## コンストラクタで指定した変数が渡される if($flag_in_title == 1 and $dtext[0] ne ''){ $str_title = $dtext[0]; } }

■ その他の方法

URI::Title を用いてもWebページのタイトルを取得できる

#!/usr/bin/perl use warnings; use strict; use utf8; use LWP::UserAgent; use HTTP::Request; use Encode; use Encode::Guess qw/shiftjis euc-jp iso-2022-jp/; use URI::Title; binmode(STDIN, ":utf8"); binmode(STDOUT, ":utf8"); my $str_title; # 抽出された title 文字列 my $enc; # 自動判定されるエンコード形式 print "title属性を抜き出します\n"; main(); exit; sub main{ # 指定されたURLよりHTMLファイルをダウンロードし $html 変数に格納する print("解析するURLを入力 : "); my $url = <>; chomp($url); if($url eq '' or $url !~ /^http:\/\//){ print("Error : 入力が無かった、又はurlが「http://」で始まっていない\n"); exit; } my $req = HTTP::Request->new(GET => "$url"); my $ua = LWP::UserAgent->new; # $ua->proxy('http', 'http://proxy:8080'); my $res = $ua->request($req); if (!$res->is_success){ print("Error : 指定したURLからファイルをダウンロードできない\n"); exit; } my $html = $res->content; $str_title = URI::Title::title($url); $enc = find_encoding($str_title); if(ref($enc)){ $str_title = $enc->decode($str_title); } print("title=".$str_title."\n"); }