bar_1

contents_map

ラベル ruby の投稿を表示しています。 すべての投稿を表示
ラベル ruby の投稿を表示しています。 すべての投稿を表示

2010年10月21日木曜日

GAE: Windows環境でRubyをつかったGoogle App Engine開発環境導入まとめとコマンドヘルプ

■本稿の目的



Googleによる App Engine のチュートリアルは、とてもわかり易く、手順をシンプルに追った記述となっている。これにより、PythonまたはJavaを使ったGAEの開発の最低限の方法について、知ることができる。



しかしながら、このチュートリアルでは、以下のような難点がある:

  • Rubyの環境については触れられていない

  • 開発用のコマンドの詳細の説明については、省かれている

  • 手順を丁寧に追っているため、記述に若干冗長な感がある




加えて、ネット上の情報を見ると、それらのほとんどはLinuxベースの環境であって、Windows+Ruby環境でのGAE開発に触れた情報は少ない(Googleでキーワード「GAE Ruby Windows dev_appserver appcfg」で検索すると、実際のページ総数はたかだか「約 244 件中 3 ページ目 (0.24 秒)」件である)。



そこで、本稿は:

  • Windows環境(ActiveScriptRuby)

  • RubyをつかったGAE開発

  • Googleのチュートリアルより記述を簡潔に

  • ただし開発用コマンドの説明は詳細まで行う

という方針で、App Engineを利用した開発の手始めについてまとめた。


■凡例


本稿の表記
Googleのチュートリアルの表記、または本稿が想定する環境等

GAEアプリ
App Engineアプリケーション
GAE SDK
App Engineソフトウェア開発キット
GAEリモート動作環境
Googleによって提供されているApp Engine (Python|Java|etc...) ランタイム
 環境。
GAEローカル環境
GAEのソースの記述、ローカルWebサーバーでテストなどをおこなうGAEリモー
ト動作環境の外、すなわちあなたのPCなどのこと。
GAEアプリID
GAEアプリのための任意のID
GAE開発用コマンド
 核となるコマンド: dev_server.rb, appcfg.rb をいう。


■Google App Engineとは



App Engineとは:

  • メールサービス

  • Webサーバー・インタフェース
    Webアプリ
    Webアプリ・開発用コンソール http://(localhost:xxxx|appid.appspot.com)/_ah/admin
     (上記Webアプリは、GAEアプリとしての特徴を有する)

  • ストレージ

を有する、Googleによるサービスの総体のことである。


これらのサービスを使って、ユーザによりGAE SDKを使って開発されるものを、本稿では、GAEアプリと呼ぶ。


GAEアプリを開発、実行する環境は、2つあり:
 GAEリモート動作環境、
 GAEローカル環境
とよぶ。
 
 



■RubyのGoogle App Engine環境



本稿では、単にApp Engineを導入するのでなくて、Rubyを用いた環境を導入する
ことを想定している。実際には、Javaの環境をベースに JRubyを介して、Rubyを
利用する形となる(一般的に提供されている、PythonやJavaによる環境ではない
��。


このRubyを利用するための環境は、 gem形式でGoogleが用意してくれている。
 



■GAEアプリ開発の一連の流れを簡潔に述べる



チュートリアルの流れを、簡潔に表にまとめた。





































ステップ用意するもの得られるものやること

1.GAE開発環境の用意

GAE SDKのダウンロード作業

GAEの開発環境

Ruby用のGAE SDKをインストールする。
方法については、

前回の記事

を参照のこと。 

2.GAEアプリのアカウントを登録

Googleアカウント、
GAEアプリID、
SMSを受信できる携帯電話

GAEアプリのURL(http://GAEアプリID.appspot.com/)

GAEアプリのアカウント登録サイトで、必要とされる情報を入力する※。


3.GAEローカル環境でのGAEアプリの開発

ソースコード

GAEアプリ

GAEアプリのソースコードを記述する。

4.GAEリモート動作環境へのアップロード

GAEアプリ、
アップロード・コマンドの実行(appcfg.rb)、
GoogleアカウントのIDとパスワード

GAEリモート動作環境でのGAEアプリの起動

アップロード・コマンドを実行し、GAEリモート動作環境にアップロードする。




※ステップ2の注意



SMSの登録内容について。電話番号の表記の仕方(81を含むのかそうでないか)、メ
ールアドレスかイマイチ判然としない。何度か試しているうちに、Googleか
らSMSが来たため、どれが正しいかわからなかった。



このサイト

でも、同様の事例をまとめているようだ。


Googleから送信されるSMSには、"Google App Engine Code: xxxxxxx"(xは数
字)という内容で、これがGoogleの GAEアカウント認証サイトによって認証
される必要がある。(当方は、ドコモの携帯電話で2010年 9月に行った。)
 
 
 
 




■GAE開発用コマンドについて



GAE SDKのをインストールすると、チュートリアルに紹介されているコマンド:
dev_appserver.rb, appcfg.rb が、ディレクトリ: %RUBY_HOME%\bin\ などに、
格納される(実際には、BATファイルからなる複数のスクリプトから構成されるが、本稿で
はここのスクリプトについての説明は割愛する)。



◆概要



●dev_appserver.rb



開発用のローカルWebサーバー兼GAEローカル環境でのGAEアプリのランチャ。
使い方:
 dev_appserver.rb [オプション] <warディレクトリ>



「warディレクトリ」にあるGAEアプリを、ローカル環境で起動する。


このローカルWebサーバーは、Googleアカウントをシミュレートしていて、独自
のログイン、ログアウト画面を有する。



●appcfg.rb



GAEアプリの管理コマンド


使い方:
 D:/PROGRA~1/ruby-1.8/bin/appcfg.rb [options] <action> <app-dir> [<output-file>]




管理とは、以下のことを指す:

  • ランタイム環境へのGAEアプリのアップロード
  • index.yamlの更新・削除
  • スケジュール・タスクの管理
  • スケジュール・タスクの管理

  • ランタイム環境へのデータのアップロード

http://code.google.com/intl/ja/appengine/docs/python/tools/uploadinganapp.html




◆GAE開発用コマンドの詳細説明




●dev_appserver.rb



開発用のローカルWebサーバー兼GAEローカル環境でのGAEアプリのランチャ。



使い方:



  <dev-appserver> [options] <war directory>

※--help オプション時も、<war directory>指定が必要



オプション:



--help, -h
 このヘルプメッセージを表示して終了。

--server=SERVER
 -s SERVER
  最新のSDKバージョンを判別に使用するサーバの指定。

--address=ADDRESS
 -a ADDRESS
  WebサーバーがバインドするローカルPC上のインタフェースのアドレスの指
  定(もしくは、0.0.0.0 で全てのインタフェース)。

--port=PORT
 -p PORT
  WebサーバーがバインドするローカルPC上のポート番号の指定。

--sdk_root=root
 格納されているSDKでオーバーライドする場合のSDK格納ディレクトリの指定。

--disable_update_check
  最新のSDKバージョンのチェックを無効に指定。




例:




D:\Program Files\ruby-1.8\usr\local\sinatra_test>dev_appserver.rb --help .
D:/Program Files/ruby-1.8/lib/ruby/gems/1.8/gems/appengine-tools-0.0.15/lib/appengine-tools/boot.rb:50: warning: `*' interpreted as argument prefix
=> Skipping update check
=> Booting DevAppServer
=> Press Ctrl-C to shutdown server
Usage: <dev-appserver> [options] <war directory>

Options:
--help, -h                 Show this help message and exit.
--server=SERVER            The server to use to determine the latest
-s SERVER                   SDK version.
--address=ADDRESS          The address of the interface on the local machine
-a ADDRESS                  to bind to (or 0.0.0.0 for all interfaces).
--port=PORT                The port number to bind to on the local machine.
-p PORT
--sdk_root=root            Overrides where the SDK is located.
--disable_update_check     Disable the check for newer SDK versions.




●appcfg.rb



GAEアプリの管理コマンド。



使い方:



 D:/PROGRA~1/ruby-1.8/bin/appcfg.rb [options] <action> <app-dir> [<output-file>]




アクション:



<action>は、以下のうちいずれか 1つである必要がある:


 help
  あるアクションのヘルプを出力する
 request_logs
  リクエスト・ログをApache共通ログ形式で出力する。
 rollback
  処理中の更新をロールバックする。
 update
  新しいバージョンのGAEアプリに更新、あるいは新規作成する。
 update_indexes
  GAEアプリのインデックス(注)を更新する。
 update_cron
  GAEアプリのcronジョブを更新する。
 update_queues
  GAEアプリのタスク・キューの定義を更新する。
 update_dos
  GAEアプリの対DoS保護の環境設定を更新する。
 version
  バージョン情報を出力する。
 cron_info
  cronジョブの次回の実行までの時間を表示する。
 run
  ユーザーのGAEアプリ環境でjrubyを実行する。
 bundle
  GAEリモート環境へのデプロイのために、ローカルのGAEアプリをパッケージングする。




'run' コマンドは、カレント・ディレクトリをGAEアプリのディレクトリと、みなします。
'help <action>' で、詳細の説明を見てください。



オプション:



-h, --help            ヘルプを表示して終了。
-s SERVER, --server=SERVER
接続を行うサーバー。
-e EMAIL, --email=EMAIL
利用するユーザ名。省略時は入力待ちに。
-H HOST, --host=HOST  全てのRPCで送られるホストヘッダの上書き。
-p PROXYHOST[:PORT], --proxy=PROXYHOST[:PORT]
指定したプロクシ・サーバを介してリクエストをプロ
する。
--proxy_httpsも指定した場合、HTTPだけがプロクシ
され、そうでなければHTTPとHTTPSの両方がなされる。
--proxy_https=PROXYHOST[:PORT]
HTTPSリクエストをプロクシするプロクシ・サーバ。
--sdk_root=root       GAE SDKの格納場所を上書きする。
--passin              標準入力からログイン・パスワードを読む。
--insecure            管理コンソールとの通信ではHTTPSを使用しない。
--enable_jar_splitting
巨大なjarファイル(> 10M)を小さなファイルに分割する。
Split large jar files (> 10M) into smaller fragments.
--jar_splitting_excludes=SUFFIXES
--enable-jar-splitting が指定された場合、コンマ
区切りでSUFFIXESに指定された拡張子にマッチするファイルは、全ての
jarファイルにおいて、分割から除外される。
When --enable-jar-splitting is set, files that match
the list of comma separated SUFFIXES will be excluded
from all jars.
--retain_upload_dir
GAEリモート環境へのアップロード時に使用した一時ディレクトリを残す。
Do not delete temporary directory used in uploading.
--compile_encoding
JSPをコンパイルするときに使用する文字エンコーディングの指定
The character encoding to use when compiling JSPs.
-n NUM_DAYS, --num_days=NUM_DAYS
ログデータを入手する日数の指定。カットオフ・ポイントは、UTCで12時
である。できるだけ全てのログを得る場合は 0 を指定する。デフォルト
値は 1 である。
Number of days worth of log data to get. The cut-off
point is midnight UTC. Use 0 to get all available
logs. Default is 1.
--severity=SEVERITY ? アプリレベルログメッセージのシビア度の指定。範囲は 0
(DEBUG) から 4 (CRITICAL)である。
Severity of app-level log messages to get. The range
is 0 (DEBUG) through 4 (CRITICAL). If omitted, only
request logs are returned.
-a, --append          既存のファイルに追記する。
-n NUM_RUNS, --num_runs=NUM_RUNS
スケジュールされた計算するための実行時間の数
Number of scheduled execution times to compute




例:



D:\Program Files\ruby-1.8\usr\local\sinatra_test>appcfg.rb --help
D:/Program Files/ruby-1.8/lib/ruby/gems/1.8/gems/appengine-tools-0.0.15/lib/appe
ngine-tools/appcfg.rb:51: warning: `*' interpreted as argument prefix
D:/Program Files/ruby-1.8/lib/ruby/gems/1.8/gems/appengine-tools-0.0.15/lib/appe
ngine-tools/boot.rb:50: warning: `*' interpreted as argument prefix

usage: D:/PROGRA~1/ruby-1.8/bin/appcfg.rb [options] <action> <app-dir> [<output-
file>]

Action must be one of:
help: Print help for a specific action.
request_logs: Write request logs in Apache common log format.
rollback: Rollback an in-progress update.
update: Create or update an app version.
update_indexes: Update application indexes.
update_cron: Update application cron jobs.
update_queues: Update application task queue definitions.
update_dos: Update application DoS protection configuration.
version: Prints version information.
cron_info: Displays times for the next several runs of each cron job.
run: run jruby in your application environment.
bundle: package your application for deployment.
The 'run' command assumes the app directory is the current directory.
Use 'help <action>' for a detailed description.

options:
-h, --help ? ? ? ? ? ?Show the help message and exit.
-s SERVER, --server=SERVER
? ? ? ? ? ? ? ? ? ? ? The server to connect to.
-e EMAIL, --email=EMAIL
? ? ? ? ? ? ? ? ? ? ? The username to use. Will prompt if omitted.
-H HOST, --host=HOST ?Overrides the Host header sent with all RPCs.
-p PROXYHOST[:PORT], --proxy=PROXYHOST[:PORT]
? ? ? ? ? ? ? ? ? ? ? Proxies requests through the given proxy server.
? ? ? ? ? ? ? ? ? ? ? If --proxy_https is also set, only HTTP will be
? ? ? ? ? ? ? ? ? ? ? proxied here, otherwise both HTTP and HTTPS will.
--proxy_https=PROXYHOST[:PORT]
? ? ? ? ? ? ? ? ? ? ? Proxies HTTPS requests through the given proxy server.
--sdk_root=root ? ? ? Overrides where the SDK is located.
--passin ? ? ? ? ? ? ?Always read the login password from stdin.
--insecure ? ? ? ? ? ?Do not use HTTPS to communicate with the Admin Console.
--enable_jar_splitting
? ? ? ? ? ? ? ? ? ? ? Split large jar files (> 10M) into smaller fragments.
--jar_splitting_excludes=SUFFIXES
? ? ? ? ? ? ? ? ? ? ? When --enable-jar-splitting is set, files that match
? ? ? ? ? ? ? ? ? ? ? the list of comma separated SUFFIXES will be excluded
? ? ? ? ? ? ? ? ? ? ? from all jars.
--retain_upload_dir
? ? ? ? ? ? ? ? ? ? ? Do not delete temporary directory used in uploading.
--compile_encoding
? ? ? ? ? ? ? ? ? ? ? The character encoding to use when compiling JSPs.
-n NUM_DAYS, --num_days=NUM_DAYS
? ? ? ? ? ? ? ? ? ? ? Number of days worth of log data to get. The cut-off
? ? ? ? ? ? ? ? ? ? ? point is midnight UTC. Use 0 to get all available
? ? ? ? ? ? ? ? ? ? ? logs. Default is 1.
--severity=SEVERITY ? Severity of app-level log messages to get. The range
? ? ? ? ? ? ? ? ? ? ? is 0 (DEBUG) through 4 (CRITICAL). If omitted, only
? ? ? ? ? ? ? ? ? ? ? request logs are returned.
-a, --append ? ? ? ? ?Append to existing file.
-n NUM_RUNS, --num_runs=NUM_RUNS
? ? ? ? ? ? ? ? ? ? ? Number of scheduled execution times to compute




■TODO




  • gem について

  • App Engine の設定項目について

  • GAE Ruby で使用されているRuby FWについて






2010年10月7日木曜日

Ruby関連 HTML/Webスクレイピング・ライブラリ・レビュー

HTML/Webのスクレイピング処理の観点から、有名どころのRubyのライブラリについて、現状(2010年10月時点)を調査した。調査項目は凡例に示すとおりである。ライブラリの比較・選定に際して、判断のひとつの材料として資することを、期待している。

なにかご意見がありましたら、お気軽にコメントをどうぞ。
2014-05-06追記: 新しいのはこちら→2014年版



■凡例



  • ■の次に、ライブラリ名 (現時点(2010年)でのバージョン)を記す

  • desc に、ライブラリの目的・機能仕様などの説明を記す

  • update に、ライブラリの更新期間を記す。ここで、yyyy-と記されている場合、yyyy年から現時点でも更新されていることを表す

  • url には、ライブラリのHPを記す。特にない場合、また情報が不足している場合は、補うに足るurl(ソースコードのurl)を追記している

  • ライセンスには、配布条件等のライセンスを記す

  • ソースコードには、ライブラリの格納場所のurlを記す

  • インストールには、ライブラリのインストール方法を記す

  • コメントには、補足の情報、私見などを記す

■Hpricot (0.8.2)


desc:
Hpricot は、非常に柔軟なHTMLパーサーで、田中 哲(TANAKA, Akira)の
HTree とジョン・レッシグ(John Lessig)の jQuery に基づいている。しかし、
コード・スキャナは、C でコーディングし直された。

update:
2006-


ライセンス:
MIT License (see http://github.com/hpricot/hpricot/blob/master/COPYING )


rubyforge:
N/A

インストール:
gem install hpricot

コメント
多くの派生ライブラリを持つHTMLパーサー。webスクレイピングにも使うこと
ができる。
以前の公式サイト(http://code.whytheluckystiff.net/hpricot/)は、リン
ク切れである。

田中 哲氏のhtreeは、 http://www.a-k-r.org/index.html からたどることがで
きる。

■Mechanize (1.0.0)


desc:
Mechanizeライブラリは、webサイト間のやり取りを自動化するために
使用される。Mechanizeは、自動でクッキーを格納して送信、リダイレクトを
フォローし、リンクをたどったり、フォームをサブミットsubmitできる。フォーム・フィ
ールドは増やしたり、サブミットできる。また、履歴となった訪れたサイトを
調査する。

update:
2005-



ソースコード:
github:
http://github.com/tenderlove/mechanize


インストール:
gem install mechanize

コメント:
Andy LesterによるPerlの同名のライブラリ:Mechanize の強い影響のもとに開
発された。webスクレイピングのためのライブラリである。
ruby 1.8.6 と nokogiri に依存している。

インストール時に、エラーが発生するという報告がWeb上に散見される。この場合、gemとRailsの更新等が事前に必要とのこと。
※追記2010/12/7:バージョン1.0.0では、Hpricotではなく、Nokogiriを使用するようになっているようだ。

■ScrAPI toolkit for Ruby (1.2.0)


desc:
CSSセレクタと選択 => 抽出 => 格納 処理ルールを使ったスクレイパーを書く
ためのフレームワーク。

update:
2006-2008



ソースコード:
github:
http://github.com/assaf/scrapi


install:
gem install scrapi

コメント:
少し情報が古い(2007年)が、このような意見もあった:“Web scraping in
Ruby: why I had to use scrAPI instead of WWW::Mechanize and Hpricot”
http://blog.bigsmoke.us/2007/05/02/scrapi-wins-over-mechanize-and-hpricot-for-web-scraping-in-ruby

開発は、止まっているようだ。

■scRUBYt! (0.4.06)


desc:
scRUBYt! は、Rubyで記述された、シンプルだがパワフルなwebスクレイピング・
ツールキットである。目的は、webページ・クローリング、HTMLタグ・属性・
XPath・フォーム名のルック・アップ処理の超めんどくささ、また、その他Web
ページまたはFirebugから直接コピペしたようなサンプルからこれらを理解
するような、典型的な低レベルなwebスクレイピングから、あなたをフリーに
することである。

update:
2007-



ソースコード:
github:
http://github.com/scrubber/scrubyt


インストール:
gem install hpricot
gem install mechanize
gem install scrubyt

コメント:
hpricot と mechanize (選択的に、AJAXのスクレイピングにFireWtir)に依存
している。

■nokogiri (1.4.3.1)


desc:
Nokogiri は、libxmlラッパーである。Nokogiri は、XPathやCSSの検索のため
のインタフェースを持ち、また、HTML, XML, SAX, そしてReaderパーサーの機
能がある。Nokogiri は、Hpricotの寄り道リプレイスメントでもある。

update:
2008-


ライセンス:
The MIT License (via http://nokogiri.org/ )

ソースコード:
github:
http://github.com/tenderlove/nokogiri/


インストール:
gem install nokogiri

コメント:
この中で、一番包括的な機能を持つパーサー。もちろん、webスクレイピングに
も使うことができる。


2008年3月18日火曜日

Ruby: Mechanize GUIDE.txt 日本語訳

追記2010/12/7:本内容は古くなったので、バージョン1.0.0のものに更新予定である。
追記2014-10-13: ここに最新版をおいた: http://voidptrjp.blogspot.jp/2014/10/mechanize-guide.html



http://mechanize.rubyforge.org/mechanize/ にある GUIDE.txt を訳してみた。
チュートリアルとしてよくできていると思う(原文的な意味で)。




  • ルー語っぽい箇所などを、若干修正[2008/3/31]

  • 訳微修正。SyntaxHighlighterでコード部分を整理[2010/8/5]








GUIDE.txt


Path:     GUIDE.txt
Last Update:     Tue Dec 04 19:36:28 -0800 2007







WWW::Mechanizeをはじめよう



このガイドは、Mechanize を使い始めるためのものです。このガイドを読み終わるまでに、ページをフェッチしたり、リンクをクリックしたり、フォームをうめてサブミットしたり、Webページ内から必要なデータを取り出したり、、と、お望みのいろいろな便利なことができるようになるとよいです。このガイドは、Mechanize を使ってできることの、表面的なほんとにちょっとしたスクラッチです。だけども、はじめるには十分な情報となるとよいです!

   


ページをフェッチしよう!



最初のことを最初に。mechanize を require して、新しい mechanizeオブジェクトを生成しましょう:

require 'rubygems'
require 'mechanize'

agent = WWW::Mechanize.new




さて、ページをフェッチするためのエージェントが使えます。グーグルをエージェントでフェッチしてみよう:

page = agent.get('http://google.com/')




なにがおこった? 我々は mechanize に対して、グーグルのメインページを取ってくるようにたのみました。Mechanize は、任意のセットされたクッキーを格納し、そしてグーグルが送ってきた任意のリダイレクトをたどりました。エージェントは、ページを我々に返しました。このページからデータを取り出したり、クリックするためのリンクを探したり、うめるためのフォームを見つけることができます。



つぎに、クリックするためのいくつかのリンクを探してみましょう。

   



リンクを見つける





Mechanize は、ページをGETしたり、POSTしたり、またはフォームをSUBMITしたとき、ページ・オブジェクトをひとつ返します。ページがフェッチされたら、エージェントはページをパースして、リンクの一覧表をページ・オブジェクト内に作ります。


それでは、グーグルのホームページをフェッチしたので、すべてのリンクを表示してみよう:

page.links.each do |link|
   puts link.text
end




リンクの一覧を表示できます。だけど、Mechanize はクリックするリンクを見つけるのに役立つ、いくつかショート・カットを用意してます。たとえば、テキストが ‘News’ であるようなリンクをクリックしたい、としましょう。ふつうは、このようにしなければなりません:

page = agent.click page.links.find { |l| l.text == 'News' }




でもMechanize には、ショートカットがあります。上記の代わりに、このようにできるのです:

page = agent.click page.links.text('News')




このショートカットは、「名前が ‘News’ であるような全てのリンクを探せ」という意味です。もしかしたら読者は「そのテキストのリンクは、複数ありうるのに!」と考えているかもしれません。そしてそれは正しい!もしクリック・メソッドに、リンクの一覧を渡した場合、Mechanize は最初のひとつをクリックします。もし二つ目のリンクをクリックしたいのなら、このようにやりましょう:

agent.click page.links.text('News')[1]




適切なリンクを以下のように探すこともできます:

page.links.href('/something')




もしくはそれらを一緒につなげて、適切なテキストと適切なhrefのリンクを探すこともできます:

page.links.text('News').href('/something')




これらのショートカットは、frame, iframe, formのようなものをフェッチしたときの任意のリストに対して、使えます。さて我々はリンクのクリックの仕方を知りました。つぎに、フォームをうめるようなもっと複雑なことをやってみましょう。

   


フォームをうめる




グーグルの例の続きをやりましょう。以下がコードです:

require 'rubygems'
require 'mechanize'

agent = WWW::Mechanize.new
page = agent.get('http://google.com/')




もしページが表示できれば、ひとつのfという名前のフォームがあり、2組のボタンと2,3のフィールドがあります:

pp page




いまフォームの名前がわかりましたので、ページをフェッチしてみましょう:

google_form = page.form('f')




Mechanize で、フォーム・インプット・フィールドにアクセスする方法はいくつかありますが、一番便利な方法は、オブジェクトのアクセッサを利用する方法です。では、フォーム上の ‘q’ という名前のフォーム・フィールドに、‘ruby mechanize’と入力して見ましょう:

google_form.q = 'ruby mechanize'




値をセットして、フォームを表示し、以下のような行が見えることを確認してください:

#<WWW::Mechanize::Field:0x1403488 @name="q", @value="ruby mechanize">




名前 ‘q’ に対応する値が変わっていた場合は、成功です!つぎにフォームをサブミットしてボタンを押し、結果を見てみましょう:

page = agent.submit(google_form, google_form.buttons.first)
pp page




今やったことは、検索フィールドに文字をいれて「検索」ボタンを押したのと同じことです。ボタンなしでフォームをサブミットした場合、テキスト・フィールドに入力してリターン・キーを打ったのと同じです。



コードを全部見てみましょう:

require 'rubygems'
require 'mechanize'

agent = WWW::Mechanize.new
page = agent.get('http://google.com/')
google_form = page.form('f')
google_form.q = 'ruby mechanize'
page = agent.submit(google_form)
pp page




ここまでで、スクリーン・スクレーピングをやってみました。フォームについて、もう少し深く見てみましょう。スキップしたくなる前に!

   





フォーム・テクニック応用編



このセクションでは、フォームで可能な入力フォームで違ったタイプの使用法について、触れたいと思う。パスワードやテキストエリア・フィールドは、テキスト・フィールドと同じように扱われ得る。セレクト・フィールドは、テキスト・フィールドにとても似ているが、関連するオプションがたくさんある。ひとつのオプションを選んだとき、mechanize はそれ以外のオプションを非選択にする (マルチセレクトでなければ!)




たとえばリスト上のひとつのオプションを選択しよう:

form.fields.name('list').options[0].select




今、チェック・ボックスとラジオ・ボタンを見てみよう。チェックボックスを選択するには、ただこのようにすればいい:

form.checkboxes.name('box').check




ラジオ・ボタンは、チェック・ボックスによく似ているが、同じ名前のその他のラジオ・ボタンをアンチェックする方法を知っている。チェック・ボタンと同じように、ラジオ・ボタンをチェックしてみよう:

form.radiobuttons.name('box')[1].check




Mechanize はまた、ファイルのアップロードも簡単にできる!ファイル・アップロード・フィールドを探し、ファイル名を教えてやるのだ:

  form.file_uploads.file_name = "somefile.jpg"


   



データをいじる





Mechanize は、HTMLをパースするために hpricot を使っている。これはなにを意味するか? mechanize で得たページを、hpricotオブジェクトのように扱えるということだ。 Mechanize をデータを取り出したいページのナビゲートに使った後、hpricotのメソッドで取り出せる:

agent.get('http://someurl.com/').search("//p[@class='posted']")


このパワフル・スクレーパに関するさらなる情報については、 HpricotBasics を参照してほしい。




2008年3月16日日曜日

Ruby: OptionParser (optparse.rb) の使い方

2014-05-13追記: 最新の OptionParser の網羅的機能については、「Ruby OptionParser クラスのリファレンス」 を参照してください。

OptionParser: コマンドライン・オプション解析のためのクラス

コマンドライン・オプションを解析するための方法として、従来からGNU の getopt 系のAPIが使われてきた (Getopt,GetoptLong)。Ruby ではこれらに加えて、optparse.rb の OptionParser クラスを利用する方法があるようだ。
ドキュメントは、たとえば http://stdlib.rubyonrails.org/ などに見つけることができる。
ここでこの OptionParser クラスは、従来の getopt 系クラスと使い勝手がだいぶ違うため、使いにくいという意見が散見される。実際、私も使ってみてその感があった。そこで、リファレンス・ドキュメントから主要な機能を抜き出して、使い方をまとめてみた。

OptionParserクラスの主要な機能および記述の方法

OptionParser は、コマンドラインの配列 ARGV を与えられると、その配列を解析しオプションのタイプに応じた処理を行う。ここで、「オプションのタイプに応じた処理」とは、実際には実装者が作りこむものである。
具体的には以下の3点を記述することになる:
  • オプションの定義
  • 定義されたオプションを指定したときの処理の定義
  • ヘルプ・メッセージの定義
以下にサンプルコードを示す。
#! /usr/bin/ruby
#filename: test-optparse.rb
#author: http://voidptr.seesaa.net
#date: Mar. 11th, 2008
#desc:
#ref.: http://stdlib.rubyonrails.org
#
####
require 'optparse';
require 'ostruct';
require 'pp';
#### Option Parse Method.
def option_parse( args )
#Prepare.
ost         = OpenStruct.new;
#default option values.
#
#
ost.help    = "";
ost.file    = "";
ost.kind    = "";
ost.logfile = "test.log";
ost.verbose = false;
ost.arr     = [];
#
op = OptionParser.new do |opars|
opars.banner = "NAME "+" #{$0} [options]";
opars.separator "";
opars.separator "";
#display -h description at tail of the help message.
#
#
#on_headだと、help表示のとき他のオプションとの間に改行される。
#お好みで。
#opars.on_head( "--version", "show the version." ) do
opars.on( "--version", "show the version." ) do
puts "green 1.0.0";
exit 1;
end
#オペランドありオプション(基本形; オペランドFILEは、必須)
#
#
opars.on( "-f FILE", "specify a file" ) do |f|
ost.file = f;
end
#オペランドありオプション(基本形+; オペランドKINDは必須で、値は選択式・短縮形も可)
#-k a で、-k afterと同じ。-k b で、-k before と同じ意味。
#
#
opars.on( "-k KIND", [:before, :after], "select a kind {before, after}" ) do |k|
ost.kind = k;
end
#オペランドありオプション(基本形++; オペランドは、省略可)
#
#
#
opars.on( "-l [LOGFILE]", "specify the logfile." ) do |l|
if ( l != nil ) then
ost.logfile = l;
end
end
#フラグタイプのオプション (オプションは長い形式もあり; offの形式も同時に定義)
#
#
opars.on( "-v", "--[no-]verbose", "verbose mode switch." ) do |v|
ost.verbose = v;
end
#フラグタイプのオプション
#  on_tail で、オプション定義の〆
#
opars.on_tail( "-t", "--tasukete", "show this message." ) do
puts opars;
exit 1;
end
end  #endof do |opars|.
####
#オプションなしの場合.
#
#
if ( args == [] ) then
#ヘルプを表示。
puts op;
exit 1;
end
#
op.parse!( args );
#必須オプションのチェック
#
#
if ( ost.file == "" ) then
e = OptionParser::ParseError.new;
e.reason = "file was NOT specified (#{ost.file}).";
throw e;
exit 1;
end
#
ost;
end  #endof option_parse
#### Do.
options = option_parse(ARGV)
#### Result.
pp ARGV;
puts "";
pp "Dumper #{options}"
puts "name: #{$0}";
####endof filename: test-optparse.rb

コードについて

OptionParser を newする際に、コード・ブロックを渡している。このコード・ブロック内でオプションの定義、処理、ヘルプメッセージの定義を記述する。
これら3要素は、このコード・ブロック内にすべてまとめて記述することになる —-つまり、ロジックとデータは煮込みすぎたスープのようにどろどろに熔けてしまっている。これは、OptionParserの特徴だ。
一般的には、このようなかたちはプログラミング・ポリシーとしてもオブジェクト指向的にもよろしからざることと思われる。グット・デザイン教会からは破門されるかもしれない。
ただ、ことコマンドライン・オプション処理に限っていえば、この方式はとても楽なのだ; 各オプションとそれらの説明を、一元管理できる。

2008年2月29日金曜日

Ruby: irb, ruby console で日本語入力ができない?

いつのまにか、そうなっていたのでいじってみた。


解決法
Step 1. ナチュラルインプットを無効にする

(1) コントロールパネル>地域と言語のオプション>テキストサービスと入力言語
で、Natural Input を選択。

(2) プロパティ>詳細設定>「詳細なテキストサービスをオフにする」を、チェック

再起動を促される。

これをおこなうと、なぜか言語バーがデスクトップに表示されなくなった。
また、コンパネの地域と言語のオプション>テキストサービスと入力言語にも、Microsoft Natural Input が消えた。


Step 2. IME使用の設定を行う

IME の詳細設定>システムの構成ペイン内>「詳細なテキストサービスをオフにする」を、チェック

IMEのバー(これも言語バー?)が、デスクトップ右下に表示される。
また、irb・ruby console ともに、Alt+漢字で日本語入力可能に。ウマー

2008年1月29日火曜日

Ruby: 数字に桁区切りを入れたい(その2)

前回 は、数字を区切るためのインスタンス・メソッドを作成した。
今回はこのクラス Price に、コンストラクタと比較演算メソッドを、追加しよう。
Price.new の引数として、文字列、または、整数をとるものとする。
オープンクラス を使って、クラスに機能を追加した。
class Price
  public

  include Comparable

  #Constructer
  #
  def initialize( p_ )
    @val_orig = p_.to_s;
    @val_s_wo_d = del_digit_delimiter( "#{@val_orig}" );
    @val_s_w_d = add_digit_delimiter( @val_s_wo_d );
    @val_i = @val_s_wo_d.to_i;
  end

  def <=>(other)
    self.val_i <=> other.val_i;
  end

end
コンストラクタ: initialize では、4種類のインスタンス変数: val_orig, val_s_wo_d, val_s_w_d, val_i; が生成される。
それぞれ、オリジナルの値、桁区切りなしの値、桁区切りありの値、数値変換時の値、となる。
インスタンス・メソッド: <=> は、クラス Price のオブジェクト同士の大小比較を行うために、定義した[1]。

References:

  • [1] 『プログラミングRuby 第2版 言語編』; ‘Mixin’, p.101

2008年1月24日木曜日

Ruby: 数字に桁区切りを入れたい (その1)

数字に桁区切りを入れたい。

クラスPriceをつくってみよう。
内部で文字列と数字で値を保存する。
class Price

protected

def add_digit_delimiter( v_ )

#remove comma from v_.

v_.gsub(/[,]/){ |c| "" };



#adding commas from lower, each 3-digits.

v_.reverse.gsub(/[[:digit:]]{3}(?=\d)/){|d| "#{d},"}.reverse;

end



[追記]2013-04-13 3の倍数桁のときに、左端にカンマが付いてしまうため修正: (?=\d)を追加した。
def del_digit_delimiter( v_ )

v_.gsub(/,/){|d| ""};

end

��

��

これで、メインとなる処理はできた。

2007年12月5日水曜日

Overloading methods in Ruby

Ruby では、メソッドなどのいわゆる多重定義(オーバロード;overload)ができない。
したがって、引数の異なる複数のコンストラクタを持つことも、できないという話。

その回避策は:
[ruby-list:30553] Re: 名前の異なるコンストラクタを複数持つには?



多重定義は、抽象化のひとつの手だとおもうのだが、Rubyのこのような仕様はC++使いからすると、あんまりうれしくない。