最近在写某脚本的时候又被Nokogiri绊倒了,一怒,决定把机上的Mechanize的html_parser换回到Hpricot去。之前 NS老兄已经这么做过一次,向他咨询了经验后,这改造工程顺利完成。下面把步骤记下来。
这次测试的机器上,我安装的是 RubyInstaller Technology Preview2的1.8.6-p383,安装到C:\Ruby。这个新的RubyInstaller装的Ruby上要安装Hpricot得先把devkit也装上才行,为了构建Hpricot用。下载 devkit-3.4.5r3-20090411.7z,解压到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要怎么构建也该了解。下面描述的步骤也对应非Windows用户,因为只涉及纯Ruby代码的修改。
都装好之后,把下面提到的几个地方改过来:(注释里的是原本的代码,上面是新改的代码)
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"])
(这两个文件里有多处相同的代码要改,不放心的话在文件里搜一下吧)
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的切换,所以改起来并不费力。只是page.rb和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