古いMechanizeスクリプトを少しモダンにする

まずは定義

古い
Ruby 1.8.5 + Mechanize 0.8 + Hpricot 前提のもの
モダン
Ruby 1.9 + Mechanize 1.0 + Nokogiri 前提のもの

Mechanize 2.0 は新しすぎるので手を出しません。

WWW::Mechanize -> Mechanize 変更

Mechanize は 1.0 で WWW ネームスペースがなくなりました。これは機械的に置き換えます。個人的には常に以下のような subclass を用意していたので、この作業はそれほど大変ではありませんでした。

Bundler でまとめて gem のバージョンを管理

gem のバージョンを gem メソッドで指定できることを知って以降、とにかくあの面倒くさい時期の Mechanize に触れないように

gem 'mechanize', '< 0.9'
require 'mechanize'
require 'hpricot'

とかやっていたのですが、個々のファイルでこのように書いていると書き直しや gem のインストールが面倒なので Bundler でまとめてしまいます。具体的には

Gemfile

を用意して、

gem 'mechanize', '< 2'

などとします。で、

bundle install

します。

system の gem を汚さない方法

もし system wide な gem に変更を加えるのが難しい場合1

bundle install --path vendor

のようにして、変更を加えるコードの場所に gem をインストールします。これ以降の作業は全部

bundle exec ./script

みたいな形で行います。この場合は利用する gem は基本的に全部 Gemfile に書いておく必要があるので、

gem 'rake'

などを書き足す必要があるかもしれません。

最初のネック - Hpricot と Nokogiri の encoding の扱いの違い

  1. Hpricot ベースの Mechanize はパース時にもページの encoding はそのままスルー
    • form や link の検索時には "ラベル".tosjis などのように変換が必要
  2. Nokogiri ベースの Mechanize はパース時の encoding はすべて UTF-8 に統一
    • UTF-8 でコードを書いている場合は form や link の検索時には何も考える必要なし ex) link_with( "ラベル" ).click
    • ただしパース前の Mechanize#page は元の encoding のまま保存されている。

到達したページから何らかの情報を取得したい場合は一度手で UTF-8 に変換しないとややこしいです。特に Nokogiri に渡し直す場合は UTF-8 への変換が必須になります。

Hpricot から Nokogiri に切り替える

  • 何はともあれ全部 UTF-8 化する
# -*- coding: utf-8 -*-
$KCODE='u' unless defined? ::Encoding

を付けて回りましょう。もちろん関連ファイルは全部 UTF-8 に統一します。もうさすがに ja_JP.eucJP な環境はない…ですよね?

  • 文字コード変換をどんどん削除
link_with( :text => 'ラベル'.tosjis ).click
-> link_with( :text => 'ラベル' ).click

これで内部で UTF-8 のパース済みデータを持っている Mechanize と比較的仲良くできます。

恐らく、当初思っていたよりは面倒は起きずになんとかなると思います。

パースに失敗する場合

もっと詳しいところがあるのでどうぞ!

Ruby 1.9 対応

上の作業だけで Mechanize 1.0 + Nokogiri 1.5 に対応できていたら、そのまま Ruby 1.9 に対応できる可能性は比較的高いです。ぜひ rvm などから ruby のバージョンを切り替えてテストしてみることをお勧めします。

ただし、1.9 ではどうしてもうまく動かない場合もあります。(いま実際にそれでハマっているコードも手元にあります。これをどうするかは今後考えます。)

  1. そんなことあるのかな? 

More

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Dev Jekyll