Mechanizeのhtml_をparserをHpricotに戻す


詳細
私が最初にNokogiriを使ったのは、Mechanize用のHTML/XML解析器がHpricotからNokogiriに移ったからだったのを覚えています.しかし、Nokogiriは問題が多く、メモリ漏れの問題は解決されていないようで、1.9で使いたいときもsegfaultで、フォーマットの悪いHTMLの解析にも問題がありました.といってもwhyは人々の視野を離れたが、whymirrorでは、現在のバージョンのHpricotを含むgithubに残るwhyのコードを見つけることができる.RubyGemsでもHpricotにインストールできます.
最近、ある脚本を书いているうちにノコギリにつまずいて、怒って、机の上のMechanizeのhtml_をparserはHpricotに戻ります.以前NSさんは一度やったことがありますが、経験を聞いてみると、この改造工事は順調に完成しました.次は手順をメモします.
今回テストしたマシンに、私が取り付けたのはRubyInstaller Technology Preview 2の1.8.6-p 383で、C:Rubyに取り付けました.この新しいRubyInstallerのRubyにHpricotをインストールするにはdevkitもインストールしなければなりません.Hpricotを構築するために使います.devkit-3.4.5 r 3-20090411.7 zをダウンロードし、Rubyのインストールディレクトリに解凍し、devkitディレクトリのMSysからコマンドラインが必要な手順を完了します.に合格
gem install mechanize

Mechanize 0.9.3にインストールできます.
gem install hpricot

Hpricot 0.8.2にインストールできます.
古い公式版RubyInstallerで装着されているRuby 1.8.6であればdevkitは不要で、RubyGemsで直接Hpricotを装着できます.もしあなたが自分で作ったRubyを使っていたら、これらのgemがどのように構築されているのかも知っておくべきだと思います.以下に説明する手順は、純粋なRubyコードの修正のみが対象であるため、Windows以外のユーザにも対応する.
すべて詰めた後、以下のいくつかの場所を変更します:(注釈の中は元のコードで、上は新しく変更したコードです)
C:\Ruby\lib\ruby\gems\1.8\specifications\mechanize-0.9.3.gemspec
C:\Ruby\lib\ruby\gems\1.8\gems\mechanize-0.9.3\mechanize.gemspec
s.add_runtime_dependency(%q, [">= 0.8.2"])
# s.add_runtime_dependency(%q, [">= 1.2.1"])
# ...
s.add_dependency(%q, [">= 0.8.2"])
# s.add_dependency(%q, [">= 1.2.1"])

(この2つのファイルに同じコードが複数あるので、不安ならファイルで検索してみましょう)
C:\Ruby\lib\ruby\gems\1.8\gems\mechanize-0.9.3\lib\www\mechanize.rb
require 'hpricot'
# require 'nokogiri'
@html_parser = Hpricot
# @html_parser = Nokogiri::HTML

C:\Ruby\lib\ruby\gems\1.8\gems\mechanize-0.9.3\lib\www\mechanize\page.rb
      def parser
        return @parser if @parser

        if body && response
          #if mech.html_parser == Nokogiri::HTML
          #  @parser = mech.html_parser.parse(html_body, nil, @encoding)
          #else
            @parser = mech.html_parser.parse(html_body)
          #end
        end

        @parser
      end

C:\Ruby\lib\ruby\gems\1.8\gems\mechanize-0.9.3\lib\www\mechanize\util.rb
        def to_native_charset(s, code=nil)
          #if Mechanize.html_parser == Nokogiri::HTML
          #  return unless s
          #  code ||= detect_charset(s)
          #  Iconv.iconv("UTF-8", code, s).join("")
          #else
            s
          #end
        end

        def from_native_charset(s, code)
          #if Mechanize.html_parser == Nokogiri::HTML
          #  return unless s
          #  Iconv.iconv(code, "UTF-8", s).join("")
          #else
            s
          #end
        end

Mechanizeのデザインはもともとhtml_を考慮していましたparserの切り替えなので、直すのに苦労しません.ただのpagerbとutil.rbにNokogiri::HTMLと明示的に書かれているのは憂鬱で、require'nokogiri'というコードを外すとNokogiri定数が定義されていないと文句を言います.
幸いにも改造前にNSに聞いたが、そうでなければgemspecの配置を変更することを知らないだろう.RubyGemsがどのように働いているのか、これまで知らなかったorz
091109更新:JRuby 1.4.0で同じようにMechanizeを改造してHpricot 0.8.2-javaでhtmlを作ってみました.parser、しばらく問題はありませんでした.やっとまたJRubyでMechanizeが使えるようになりました、涙目TvT