努力してみた日記

最新 追記
あまりためにはならない話しか書かないと思うよ。

努力したWiki

2012-06-10 Methods.pmに泣かされた話

[www] WWW::Mechanizeで困った話

WWW::Mechanize と Web::Scraperを使ったサイトのクロールをやってて遭遇したエラーの話。

これ、環境や相手にするサイトによっては全く遭遇する事のない場合もあってなかなか面倒です。実際、会社では泣きが入るくらい遭遇したのに、家で同じように実行してみても全く再現しませんでした。

とりあえずこんなコードは良く見かけますが例を挙げておきます。yatopic.plとでもしておきましょうか。

use Encode;
use WWW::Mechanize;
use Web::Scraper;
 
my $baseUrl  = 'http://dailynews.yahoo.co.jp';
my $yahooUrl = 'http://dailynews.yahoo.co.jp/fc/';
my $encstr   = 'euc-jp';
my $mech     = WWW::Mechanize->new(autocheck=>1);
 
my $topicsMenuParse = scraper {
      process '//div[@id="globalNav"]/ul[@id="gnSec"]//li',  "menulinks[]"=> scraper {
           process "a", href=>'@href';
           process "a", text=>"TEXT";
      }
};
 
my $topicsLinkParse = scraper {
      process '//div[@id="topics"]/div[@class="topicsList"]/ul[@class="clr"]//li', "topiclinks[]"=> scraper {
           process "span", date=>"TEXT";
           process "a",    href=>'@href';
           process "a",    text=>"TEXT";
      }
};
 
my $menuResult;
 
  $mech->agent_alias("Windows Mozilla");
 
  $mech->get( $yahooUrl );
  $menuResult = $topicsMenuParse->scrape( $mech->content );
 
  foreach my $categoryLink ( @{ $menuResult->{menulinks} } )
  {
      my $topicResult;
      my $text = encode($encstr, $categoryLink->{text});
      my $href = encode($encstr, $categoryLink->{href});
 
        printf("*** %s ( %s )\n",  $text, $href);
 
        $mech->get( "".$categoryLink->{href} );
        $topicResult = $topicsLinkParse->scrape( $mech->content );
 
        for my $topicLink ( @{ $topicResult->{topiclinks} } )
        {
           my $date = encode($encstr, $topicLink->{date});
           my $text = encode($encstr, $topicLink->{text});
           my $href = encode($encstr, $topicLink->{href});
 
           printf("%s %s ( %s )\n",  $date, $text, $baseUrl.$href);
        }
  }

RSSで取得できるわい、と言われちゃいそうですけどね

yatopic.plでは、WWW::MechanizeでYahoo!ニュースのトピックスページを取得、Web::Scraperで利用するHTML要素の切り出しを行っています。

今時ならRSSで配信されている事も多いのでそちらを使う方が楽なのですが、配信していないサイトではHTMLを直接パースして必要な部分を抜き出さなきゃなりません。それに、今回会社で喰らったのはトピック切り出しじゃ無いのでRSSじゃ取得が出来ません。はい。

$mech->content の中身が中途半端な場合あり...

で。会社でも同じようなスクリプトを書いて、某社の問題情報ページをテキスト化していた時に、なぜか中身がまっさらな出力をするページがあったりしました。というかほとんどがそれ。ブラウザで表示できるのは確認していたのでWeb::Scraperの記述ミスの確認やら何やら、最後はプロキシの問題かとも思いましたが、動いちゃう時もある。うーん。

そして$mech->content をファイルに吐いて確認すると、あれ?取得したHTMLが途切れてる.....そりゃWeb::Scraperが動けないよね......

at Methods.pm line 481.

若様から「Content-Lengthヘッダの長さがおかしいとか?」と言われ、レスポンスヘッダをダンプしてみたらContent-Lengthヘッダは無し。

WWW::Mechanize自身が取得しているレスポンスヘッダのダンプを $mech->dump_headers()で出してみたところ、..あれれ? X-Died ?

X-Died: Missing newline after chunk data: '>' at /usr/local/lib/perl5/site_perl/Net/HTTP/Methods.pm line 481.

[努力中の人の記憶より引用]

net/p5-Net-HTTPの問題っぽい

早速この表示を元にGoogle先生のご神託を聞いてみる。...どうやらLow-level HTTP client(p5-Net-HTTP)の問題らしいです。コンテンツがチャンクにされて(このチャンクがHTTP上の話か、Net::HTTPの処理上の話かは不明)このチャンクを扱おうとした際に処理に失敗する事があると。途中でHTMLが途切れているのは、このチャンクの処理に失敗したから。

だから、チャンクの扱いに失敗しないとうまくいく、と。

このパッケージは色々なパッケージで使われているものらしく、Mechanize以外にもLWP::UserAgentで問題が出ていたりするようです。

これに関して、debian-bugs-dist Bug#674788: LWP::UserAgent cuts chunked response の解決策の適用で、あっさり問題が解決してしまいました。/usr/local/lib/perl5/site_perl/Net/HTTP/Methods.pm に直接手を入れることになるので、バックアップは忘れずに。

ちなみにこのコードの実行結果はこうなります

$ perl yatopic.pl
*** 国内 ( http://dailynews.yahoo.co.jp/fc/domestic/ )
6月9日 13時41分 再稼働「福島の教訓どこへ」 ( http://dailynews.yahoo.co.jp/fc/domestic/fukushima_1np_evacuation/ )
6月9日 15時37分 再稼働は夏限定で 大阪府市 ( http://dailynews.yahoo.co.jp/fc/economy/electric_companies/ )
6月9日 21時23分 「全員撤退」意図なしと認定 ( http://dailynews.yahoo.co.jp/fc/domestic/fukushima_nuclear_plant/ )
6月9日 20時47分 避難継続住民 5年後32%と予測 ( http://dailynews.yahoo.co.jp/fc/domestic/fukushima_return/ )
6月9日 15時49分 党首会談、15日前後を検討 ( http://dailynews.yahoo.co.jp/fc/domestic/consumption_tax/ )
6月9日 17時33分 防衛相 沖縄反発で早くも試練 ( http://dailynews.yahoo.co.jp/fc/local/futenma/ )
6月9日 16時13分 高橋容疑者との駆け落ち装う ( http://dailynews.yahoo.co.jp/fc/domestic/aum/ )
6月9日 19時34分 300億円寄付で浜松に防潮堤 ( http://dailynews.yahoo.co.jp/fc/domestic/tsunami_protection/ )
*** 海外 ( http://dailynews.yahoo.co.jp/fc/world/ )
6月9日 20時25分 シリア 虐殺の村の映像公開 ( http://dailynews.yahoo.co.jp/fc/world/syria/ )
6月9日 17時39分 米国民の60% シリア介入不要 ( http://dailynews.yahoo.co.jp/fc/world/usa/ )
6月9日 22時29分 北、強硬姿勢をトーンダウン ( http://dailynews.yahoo.co.jp/fc/world/south_north_korea/ )
6月9日 13時35分 PKO隊員7人死亡 西アフリカ ( http://dailynews.yahoo.co.jp/fc/world/cote_d_ivoire/ )
6月9日 14時38分 JT系などに4兆円請求 カナダ ( http://dailynews.yahoo.co.jp/fc/world/canada/ )
6月9日 22時9分 陳氏迫害指揮の幹部を解任か ( http://dailynews.yahoo.co.jp/fc/world/china_human_rights/ )
6月9日 16時6分 毛沢東 天皇制肯定していた ( http://dailynews.yahoo.co.jp/fc/world/china_communist_party/ )
6月9日 17時55分 米投資家との昼食権 2億円超 ( http://dailynews.yahoo.co.jp/fc/computer/internet_auction/ )
*** 経済 ( http://dailynews.yahoo.co.jp/fc/economy/ )
6月10日 4時27分 スペインに最大10兆円支援へ ( http://dailynews.yahoo.co.jp/fc/world/spain/ )
6月9日 11時42分 UBS FB上場で280億円の損失も ( http://dailynews.yahoo.co.jp/fc/computer/facebook/ )
6月9日 3時18分 ルネサス 賃金7.5%カット提案 ( http://dailynews.yahoo.co.jp/fc/economy/semiconductors_and_computer_chips/ )
6月9日 1時47分 オリンパス、2700人削減へ ( http://dailynews.yahoo.co.jp/fc/economy/olympus/ )
6月9日 18時44分 快眠ビジネス 節電を商機に ( http://dailynews.yahoo.co.jp/fc/domestic/setsuden/ )
6月9日 9時42分 「カラムーチョ」タイ進出へ ( http://dailynews.yahoo.co.jp/fc/economy/confenctionery/ )
6月9日 16時9分 タダノ米子会社で7億円着服か ( http://dailynews.yahoo.co.jp/fc/domestic/embezzlement/ )
6月8日 22時50分 ネット時代の文章術は起承結? ( http://dailynews.yahoo.co.jp/fc/economy/business_hacks/ )
*** エンターテインメント ( http://dailynews.yahoo.co.jp/fc/entertainment/ )
6月9日 8時47分 AKB大島V報告「獲ったどぉ」 ( http://dailynews.yahoo.co.jp/fc/entertainment/yuko_oshima/ )
6月9日 5時16分 AKB前田&秋元氏 ラジオ対談へ ( http://dailynews.yahoo.co.jp/fc/entertainment/maeda_atsuko/ )
6月10日 1時16分 離婚裁判中の美元 ブログ休止 ( http://dailynews.yahoo.co.jp/fc/entertainment/entertainer_blog/ )
6月9日 22時52分 TKO木本、肺炎で1週間入院 ( http://dailynews.yahoo.co.jp/fc/entertainment/owarai/ )
6月9日 18時59分 綾瀬、雨にも負けず花嫁姿 ( http://dailynews.yahoo.co.jp/fc/entertainment/movie/ )
6月9日 8時18分 TOKIO松岡 サウナやめません ( http://dailynews.yahoo.co.jp/fc/entertainment/johnnys/ )
6月9日 9時1分 スギちゃん「GTO」で初演技 ( http://dailynews.yahoo.co.jp/fc/entertainment/sereal_tv_drama/ )
6月9日 16時49分 L・ローハン 大きな外傷なし ( http://dailynews.yahoo.co.jp/fc/entertainment/lindsay_lohan/ )
*** スポーツ ( http://dailynews.yahoo.co.jp/fc/sports/ )
6月10日 5時46分 EURO ドイツがポルトガル下す ( http://dailynews.yahoo.co.jp/fc/sports/euro2012/ )
6月9日 22時22分 ザックJを支えるバルサの原理 ( http://dailynews.yahoo.co.jp/fc/sports/alberto_zaccheroni/ )
6月9日 17時36分 FIFAサイト 本田はヒーロー ( http://dailynews.yahoo.co.jp/fc/sports/keisuke_honda/ )
6月10日 0時5分 シャラポワが4大大会全制覇 ( http://dailynews.yahoo.co.jp/fc/sports/tennis/ )
6月9日 20時56分 潮田、熱愛報道で頭下げる ( http://dailynews.yahoo.co.jp/fc/sports/ogushio/ )
6月9日 18時19分 4番勝負で火 G村田サヨナラ打 ( http://dailynews.yahoo.co.jp/fc/sports/giants/ )
6月9日 22時53分 福島がラスト30m逆転V 100m ( http://dailynews.yahoo.co.jp/fc/sports/fukushima_chisato/ )
6月10日 5時19分 男子バレー 日本の五輪条件は ( http://dailynews.yahoo.co.jp/fc/sports/volleyball_men_national_team/ )
*** コンピュータ ( http://dailynews.yahoo.co.jp/fc/computer/ )
6月9日 19時47分 WWDC「iOS 6」の垂れ幕登場 ( http://dailynews.yahoo.co.jp/fc/economy/apple/ )
6月8日 16時53分 半年経過 iPhone4S満足度は ( http://dailynews.yahoo.co.jp/fc/computer/iphone/ )
6月9日 15時4分 Appleの初代パソコン 競売に ( http://dailynews.yahoo.co.jp/fc/entertainment/auctions/ )
6月8日 12時2分 市場がWii Uを評価しない理由 ( http://dailynews.yahoo.co.jp/fc/entertainment/wii_u/ )
6月8日 20時49分 AKB総選挙に便乗マルウエア ( http://dailynews.yahoo.co.jp/fc/computer/internet_viruses/ )
6月8日 22時14分 ニフティ複数障害の内容発表 ( http://dailynews.yahoo.co.jp/fc/computer/internet/ )
6月8日 23時8分 WiMAX 天望回廊で利用可能に ( http://dailynews.yahoo.co.jp/fc/computer/wimax/ )
6月7日 22時22分 ミラーレス一眼5機種を比較 ( http://dailynews.yahoo.co.jp/fc/computer/digital_single_lens_reflex_camera/ )
*** サイエンス ( http://dailynews.yahoo.co.jp/fc/science/ )
6月9日 20時21分 中国、初の有人ドッキングへ ( http://dailynews.yahoo.co.jp/fc/world/china_space_exploration/ )
6月10日 6時28分 唾液腺と涙腺の再生実験成功 ( http://dailynews.yahoo.co.jp/fc/science/regenerative_medicine/ )
6月9日 8時51分 老化引き起こす物質を特定 ( http://dailynews.yahoo.co.jp/fc/science/lifestyle_disease/ )
6月9日 16時6分 北極海最強サメ 時速は1キロ ( http://dailynews.yahoo.co.jp/fc/science/life_on_earth/ )
6月9日 22時45分 巣立ったトキ、姿確認できず ( http://dailynews.yahoo.co.jp/fc/science/nipponia_nippon/ )
6月8日 19時25分 今年こそツチノコ 賞金1億円 ( http://dailynews.yahoo.co.jp/fc/science/uma_ufo/ )
6月8日 17時28分 親鸞の妻? 玉日姫の骨発見か ( http://dailynews.yahoo.co.jp/fc/domestic/archaeology/ )
6月10日 3時48分 兵馬俑に「放火」は項羽か ( http://dailynews.yahoo.co.jp/fc/world/world_heritage/ )
*** 地域 ( http://dailynews.yahoo.co.jp/fc/local/ )
6月10日 7時14分 飲食店に催涙ガスか 12人搬送 ( http://dailynews.yahoo.co.jp/fc/domestic/first_aid/ )
6月9日 17時8分 正面衝突で5人死亡 福島 ( http://dailynews.yahoo.co.jp/fc/domestic/traffic_accident/ )
6月9日 16時46分 違法? 幼稚園予算を保育園に ( http://dailynews.yahoo.co.jp/fc/domestic/child_care/ )
6月9日 16時2分 釜石市 がれき使いラグビー場 ( http://dailynews.yahoo.co.jp/fc/local/kamaishi_tsunami/ )
6月9日 16時36分 転落死 強盗致死で2人再逮捕 ( http://dailynews.yahoo.co.jp/fc/domestic/robbery/ )
6月9日 21時23分 ドライアイスで爆発 中2負傷 ( http://dailynews.yahoo.co.jp/fc/domestic/explosion/ )
6月9日 21時42分 猫やハト止まらぬ惨殺 兵庫 ( http://dailynews.yahoo.co.jp/fc/domestic/cruelty_to_animals/ )
6月9日 15時3分 ゲートブリッジ 自転車望む声 ( http://dailynews.yahoo.co.jp/fc/local/sightseeing/ )
*** バックナンバー ( http://backnumber.dailynews.yahoo.co.jp/ )
*** 編集センター ( http://dailynews.yahoo.co.jp/fc/editcenter/ )
$

単なる覚書以下の内容です。一度内容を全部消しました。
最新 追記
2010|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|03|04|05|06|07|08|09|11|12|
2013|01|02|03|04|06|08|
2014|02|04|06|07|09|10|11|12|
2015|01|02|03|04|06|08|09|10|11|12|
2016|01|02|04|05|10|
2017|02|03|04|05|06|09|10|
2018|04|