HTMLの閉じタグが抜けていたり、HTMLの構造がおかしいサイトがある。これをMechanizeすると困ることになる。MechanizeがParseできなくてこまるんです。つまりNokogiriがエラーになったり、Nodeがウマく取れなくてFormのInputが無かったり、有るべきリンクがなかったりする。それは困る。
だけど、HTMLのミスは結構どうしようもない。
HTMLのミスに対応しようと思うと面倒。HTMLの受け渡しは、Mechanizeの本体で行なわれてるので、本気で対応しようするとと結構面倒な事になる。間違ってMyMechanizeクラス作りかけてた。あらためてMechanizeのヘルプを読み直すと、パーサーだけを入れ替える例を見つけたのでコレでErrorがあるHTMLに対応してみた。
プラグインでHTMLエラーに対応する。
MyPageクラス
class MyParser < Mechanize::Page def initialize(uri=nil, response=nil, body=nil, code=nil, mech=nil) super(uri, response, body, code, mech) #その他HTMLソースを弄くるのはココに書く # たとえば多すぎるDiv閉じを減らす body.sub! %'</div></div></div></div>' , '</div></div>' # たとえば formの飛び先をHTMLソースレベルで変える body.sub! %'<form action=hoge.php>' , '<form action=hoge2.php>' end end agent.pluggable_parser.html = MyParser #parserを差し替える
使い方
require 'kconv' require 'mechanize' require 'MyPage.rb' agent = Mechanize.new agent.pluggable_parser.html = MyParser #parserを差し替える agent.get(url) #HTMLにミスがあるページURL puts agent.page.body.to_html.toutf8 #=> 置換済みのHTMLが出てくる
ruby はオープンClassなので、Mechanize::Page#initializeを再定義しても良いんだけど、ソース読んで分かりにくくなるのでやめた。
動きの解説
プラグイン機構でPageを自分のMyPageに差し替える。Formクラスは、init on Readですね。
なので、page.formsが呼び出されて初めてHTMLソースコードを解析し、Newする。なのでFORMSが作られる前のタイミング(この場合はinitialize)でソースコードをかきかえておくのでした。
閉じ忘れ以外の対応
HTMLのタグ閉じ忘れや、ネストがおかしい場合は、コレで対応できる。