03 May 2011

(Perl) sitemap.xml の全URLをW3C HTML Validatorでチェックするスクリプト

sitemap.xml内の全URLをW3C HTML Validatorで連続して検査し、結果をHTMLファイルに書き込むスクリプト。

攻撃と思われては困るので、1個のURLを検査した後に、10秒スリープする仕様とした。
(約100個のURL検査したら、”Could not contact validator” を返されたので、60秒くらいスリープしたほうがよかったのか…。 どうも攻撃と思われたようです。スイマセン)

→ 『 (Perl) ローカルにインストールしたW3C Markup Validatorを用いてWebService::Validator::HTML::W3Cでのチェックを行う 』 の記事も併せてお読みください。

#!/usr/bin/perl use strict; use warnings; use utf8; use File::Basename; use Getopt::Long; use XML::Parser; use XML::SimpleObject; use WebService::Validator::HTML::W3C; my $xml_filepath; my $output_html; my @arr_urls; my $wait_sec = 60; # wait 60 second, for W3C server load control # プログラム引数を取り込む GetOptions('xml=s' => \$xml_filepath, 'output=s' => \$output_html); if(!defined($xml_filepath) || !defined($output_html)){ die("W3C html validator\n usage :\n ".basename($0)." -xml=[sitemap.xml] -output=[out.html]\n"); } # 無効文字のチェックと削除 $xml_filepath =~ s/[\x00-\x2c|\x3a-\x40|\x5b-\x5e|\x60|\x7b-\xff]//g; $output_html =~ s/[\x00-\x2c|\x3a-\x40|\x5b-\x5e|\x60|\x7b-\xff]//g; unless( -f $xml_filepath ){ die("Error : sitemap file ".$xml_filepath." not found\n"); } print("Target File : ".$xml_filepath."\nOutput File : ".$output_html."\n"); # XMLからURLを抜き出して配列に格納する my $p = new XML::Parser(Style=>'Tree'); my $s = new XML::SimpleObject($p->parsefile($xml_filepath)); my @arr = $s->child('urlset')->child('url'); foreach(@arr){ push(@arr_urls, $_->child('loc')->value); } if($#arr_urls < 0){ die("Error : no url found from sitemap file\n"); } print(($#arr_urls+1)." URLs found.\nW3C query start ...\n"); my $v = WebService::Validator::HTML::W3C->new(detailed => 1); open(FH, '>'.$output_html) or die("Error : ".$output_html." open error\n"); # バッファリング無効化 my $old_fh = select FH; $|=1; select $old_fh; print(FH "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n". "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n". "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"ja-JP\" xml:lang=\"ja-JP\">\n". "<head>\n". "<title>W3C html validator result</title>\n". "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n". "<style type=\"text/css\">\n". "table { border:1px solid rgb(153, 51, 51); border-collapse:collapse;". " font-size: 10pt; margin: 10px; }\n". "th { font-weight: normal; background:#f8ede2; border:1px solid rgb(153, 51, 51);". " padding: 0.2em 0.4em; text-align: left; }\n". "td { border:1px solid rgb(153, 51, 51); padding: 0.2em 0.4em; }\n". "</style>\n". "</head>\n". "<body>\n". "<p>".($#arr_urls+1)." URLs</p>\n". "<table>\n"); foreach(@arr_urls){ my $target_url = $_; print(" ".$target_url."\n"); if($v->validate($target_url)){ if ( $v->is_valid ) { printf (FH "<tr><th colspan=\"3\"><a target=\"_blank\" href=\"%s\">%s</a> : valid</th></tr>\n", $v->uri, $v->uri); } else { printf (FH "<tr><th colspan=\"3\"><a target=\"_blank\" href=\"%s\">%s</a> : not valid</th></tr>\n", $v->uri, $v->uri); foreach my $error ( @{$v->errors} ) { printf(FH "<tr><td></td><td>%d</td><td>%s</td></tr>\n", $error->line, $error->msg); } } } else { printf (FH "<tr><th colspan=\"3\"><a target=\"_blank\" href=\"%s\">%s</a> : Fatal Error : %s</th></tr>\n", $target_url, $target_url, $v->validator_error); } sleep($wait_sec); # W3Cサーバ負荷防止のため、ウエイトを入れる } print(FH "</table>\n</body>\n</html>\n"); close(FH); print("program end\n");

■ (入力ファイル) sitemap.xml のサンプル

<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>http://netlog.jpn.org/r271-635/</loc> <priority>1.0</priority> </url> <url> <loc>http://netlog.jpn.org/r271-635/2011/05/linux_conky_and_screenlets.html</loc> <lastmod>2011-05-01T05:45:50Z</lastmod> </url> <url> <loc>http://netlog.jpn.org/r271-635/2011/04/ubuntu_freebsd_locale.html</loc> <lastmod>2011-04-30T07:16:29Z</lastmod> </url> </urlset>

■ 出力されるHTMLファイルの例

FirefoxのHTML Validatorを全て通過しているにもかかわらず、これだけのエラーが出る…

20110503-validator.jpg