BLOGTIMES
» ArchiveList
Home (Tag for "ruby")
«Prev || 1 · 2 · 3 · 4 · 5 · 6 · | Next»
2010/03/08
[ by hsur at 21:20]

SQLiteの高速化とトランザクション

 

SQLiteはファイルベースだとINSERTがあまり速くないなと思っていたのですが、ググってみると大量にINSERTを発行したい場合は明示的にトランザクションを使うというのが定番のテクニックだということがわかって愕然としました。SQLiteはAUTOCOMMITだとトランザクションが発生しない訳ではなくて、内部的にはINSERTの度にBEGINとCOMMITが発行されてしまうような仕組みなんでしょうかね。

ファイルベースのベンチマーク (INSERT*100回)

$ ./test.rb
                user     system      total        real
AUTOCOMMIT   0.000000   0.010000   0.010000 ( 16.499489)
TRANSACTION  0.010000   0.000000   0.010000 (  0.199884)

インメモリのベンチマーク (INSERT*100000回)

$ ./test2.rb
                user     system      total        real
AUTOCOMMIT   3.150000   0.350000   3.500000 (  3.508833)
TRANSACTION  3.090000   0.340000   3.430000 (  3.444818)

確かにベンチマークを取ってみると、全然速度が違いますね。インメモリの場合もほんのわずかだけ明示的にトランザクションを指定した方が速いようです。同じマシンでもファイルベースとインメモリでインサート速度が劇的に違うところもなかなか興味深いです。

 [続きを読む...]
Category: Tips | / | Comment(0) | TrackBack(0) | Permalink |
2010/02/27
[ by hsur at 16:23]

英語でない部分のスペースを削除する

 

下記のようなわざとスペースがところどころに挿入されている日本語を形態素解析したいと思って、前処理として余計なスペースを取り除く処理を書こうとしたのですが、思いのほか手こずってしまったので、後学のためにメモ。

str = <<EOS
ち ょ っ と ワ ケ あ っ て MS の ナ レ ッ  ジ ベ ー ス  を 検 索 し て い た ら  最 後 に 「The behavior is by design」と 書 い  て あ るのを見つけてしまいました。
EOS

はじめに書いたコード

単純にスペースを削除するようなコードなのですが、英語の部分があると単語が全部つながってしまうのでこれはNG。

puts str.gsub(/ +/,'')
#=>ちょっとワケあってMSのナレッジベースを検索していたら最後に「Thebehaviorisbydesign」と書いてあるのを見つけてしまいました。

最終的に書いたコード

最終的に書いたコードは下記。
文字クラスの指定が16進になっていますが、これが半角の英数字記号を表しています*1

puts str.gsub(/([^\x21-\x7E]) +([^\x21-\x7E])/,'\1\2')
#=>ちょっとワケあって MS のナレッジベースを検索していたら最後に「The behavior is by design」と書いてあるのを見つけてしまいました。
  • *1: ASCIIコード表を確認すると分かりますが、スペースを除く可視文字が !(0x21)~~(0x7e) に存在するためです。
Category: Tips | | Comment(0) | TrackBack(0) | Permalink |
2010/02/16
[ by hsur at 23:57]

Rubyのスレッド中の例外でハマった

 

Rubyでスレッドをつかったプログラムを作ったら、凡ミスを修正するのに苦戦してしまったのでメモ。結論から述べると、ThreadはjoinしたときにThread内で起こった例外が再度スローされるので、自分で立てたスレッドを確実にjoinすることがエラーハンドリングでは重要みたい。

例えば下記のコードはhogeという関数は定義されていないので、スレッドt1はこの部分でエラーになるはず。ところが、このプログラムを起動してみると、意図した動作もせず、エラーも出ないという不思議な状態になります。今回はこの状態だったので、手がかりが少なくていろいろと大変でした。

test0.rb

require 'thread'

Thread.abort_on_exception = false ###

q = Queue.new
t1 = Thread.new do
 hoge ###
 10.times do |i|
   q.enq "message! #{i}"
 end
 q.enq nil
end

t2 = Thread.new do
  while i = q.deq
    puts i
  end
end

#t1.join ###
#t2.join ###

test0.rb実行結果

ruby test0.rb
 [続きを読む...]
Category: Tips | | Comment(0) | TrackBack(0) | Permalink |
2010/02/15
[ by hsur at 13:46]

Anemoneというクローラーフレームワークを使ってみる

 

これまでクローラー使い捨てのクローラーは結構力業で作ってきたのですが、さすがにこういうことをやり始めてから1年以上が経ちこのままでは立ちゆかない事がいろいろと顕在化してきたので、クローラーを作るためのフレームワークをいろいろ調べていました。

JavaであればLuceneのサブプロジェクトであるNutchや、Seasarプロジェクトで開発されているS2Robot、PerlであればGunghoあたりに興味があるのですが、後処理の部分はRubyで書いてしまってあるので今回はAnemoneというフレームワークをつかってみることにします。

Anemone - Ruby Web-Spider Framework

Anemone is a Ruby library that makes it quick and painless to write programs that spider a website. It provides a simple DSL for performing actions on every page of a site, skipping certain URLs, and calculating the shortest path to a given page on a site.

The multi-threaded design makes Anemone fast. The API makes it simple. And the expressiveness of Ruby makes it powerful.
 [続きを読む...]
Category: Tips | / | Comment(0) | TrackBack(0) | Permalink |
2010/02/11
[ by hsur at 20:21]

MechanizeでUTF-8以外のページをスクレイピングするときの文字化け対策

 

RubyのMechanizeはスクレイピングをするときにとても便利なライブラリですが、UTF-8以外のページだとどうしてもうまく取得出来ないページがあって困っていたのですが、「Mechanize Nokogiri の非JIS文字対応 - それはそれ。これはこれ。」というエントリを参考にworkaroundを追加してなんとか回避することに成功したのでメモ。

require 'rubygems'
require 'mechanize'
require 'nkf'

agent = WWW::Mechanize.new
agent.user_agent_alias = "Windows IE 7"

# workaround
agent.post_connect_hooks << Proc.new do |params|
  if %r|text| =~ params[:response]["Content-Type"]
    params[:response_body] = NKF.nkf("-wm0",params[:response_body])
    params[:response_body].gsub(/<meta[^>]*>/) do |meta|
      meta.sub(/Shift_JIS|SJIS|EUC-JP/i,"UTF-8")
    end
    params[:response]["Content-Type"]="text/html; charset=utf-8"
  end
end

agent.get("http://example.jp/")

ほとんど参考にしたエントリそのままですが、共通のルーチンでいろんなエンコードに対応させたかったので、NKFの引数から入力エンコーディングの指定を取り去ったり、metaタグ内の"Content-Typeのエンコーディングの書き換えについてはちょっと手を入れています。

フックをつかってパーサーに渡る前の文字列のエンコーディングをあらかじめ変更しておいてあげるというなかなかの力業ですが、Nokogiri内の処理が信頼できない以上、それもいたしかたないですね。

Category: Tips | / | Comment(0) | TrackBack(0) | Permalink |
2010/01/30
[ by hsur at 21:06]

HpricotのXPath実装はちゃんとしてない?

 

HpricotのXPathの実装が完全でないことは薄々気づいていたものの、新たなライブラリを探すのも面倒だと思ってそのままにしていたのですが、とうとうちゃんと処理できない事例にあたってしまいました。

今回処理をしようとしたのは下記のコード中のようなHTMLから「<h2>aaa111</h2>の直後の<div class="a">の中身のテキストを取り出す」というもの。取り出したいdivにidなんかがついていればいいのですが、ちゃんと構造化されていないHTMLなのでどうしようもありません。

<html>
<head><title>test</title></head>
<body>
<div class="b">001</div>
<h2>aaa111</h2>
<div class="a">002</div>
<div class="b">003</div>
<div class="b">004</div>
<h2>aaa222</h2>
<div class="a">005</div>
<div class="b">006</div>
<div class="b">007</div>
</body>
</html>

とりあえずノードを指定するXPathである //h2[text() = 'aaa111']/following-sibling::div[@class='b'][1]/text() はすぐに書けたのですが、Hpricotだと結果がきちんと帰ってきません。どうやらfollowing-siblingが使えないようです。ちなみに同じXPathをNokogiriに食わせるときちんと結果が帰ってくることが確認できたので、これを機にNokogiriに乗り換えてしまうことにしました。

 [続きを読む...]
Category: Tips | / | Comment(0) | TrackBack(0) | Permalink |
2010/01/18
[ by hsur at 18:44]

SQLiteをインメモリで使う

 

SQLiteはデータのちょっとした加工や管理に便利なので、最近よく使っているのですが、ファイルの指定を:memory:とすると、インメモリで使うことができるという機能をみつけたので、Rubyからちょっと使ってみました。

In-Memory Databases

For example:
rc = sqlite3_open(":memory:", &db);

When this is done, no disk file is opened. Instead, a new database is created purely in memory. The database ceases to exist as soon as the database connection is closed. Every :memory: database is distinct from every other. So, opening two database connections each with the filename ":memory:" will create two independent in-memory databases.
 [続きを読む...]
Category: Tips | / | Comment(0) | TrackBack(0) | Permalink |
2010/01/05
[ by hsur at 21:47]

net/httpでUser-Agentをセットする

 

rubyのnet/httpを使うと、デフォルトではUser-Agentがセットされないのがちょっと気持ち悪かったので、リクエストにUser-Agentをセットする方法を調べてみました。
ちなみにopen-uriでも同じ方法が使える*1ようです。

ua_test.rb

#!/usr/bin/ruby

require 'net/http'
Net::HTTP.version_1_2
USER_AGENT= "TestAgent"

Net::HTTP.start('127.0.0.1', 80) {|http|
  response = http.get('/')
  response = http.get('/', 'User-Agent' => USER_AGENT )
}

こんな感じで追加のヘッダとして定義してあげればいいようです。
上記の実行結果のログはこんな感じ。

access_log

127.0.0.1 - - [05/Jan/2010:21:26:31 +0900] "GET / HTTP/1.1" 200 2343 "-" "-"
127.0.0.1 - - [05/Jan/2010:21:26:31 +0900] "GET / HTTP/1.1" 200 2343 "-" "TestAgent"
  • *1: 「ハッシュ引数で、追加のヘッダフィールドを指定できます。」の部分を参照
Category: Tips | | Comment(0) | TrackBack(0) | Permalink |
2009/12/12
[ by hsur at 23:55]

XML-RPCを使ってTracのチケットに添付ファイルを投げ込む(Ruby編)

 

以前に間に合わせで書いたTracにXML-RPCを投げるスクリプトがPerlだったのでRubyに書き換えようと思って作業を始めてみたら思ったより手間がかかってしまいました。

ブラウザはどちらも同じように認証用のダイアログを出してくるので分かりにくいのですが、TracLightningを使ってTracをインストールすると、認証はBasic認証ではなくてDigest認証になっています。このDigest認証をXML-RPC時にやるというのがかなりの曲者です。初めこれをすっかり忘れていて、XMLRPC::Clientを使って実装した後に認証が通らなくて色々調べる羽目になりました。

/usr/lib/ruby/1.8/xmlrpc/client.rb

If ((|user|)) and ((|password|)) are given, each time a request is send, a Authorization header is send. Currently only Basic Authentification is implemented no Digest.

上記の通り、rubyのXML-RPCライブラリであるXMLRPC::ClientはDigest認証に対応していません。
というか、僕の調べた限りではnet/httpなどのRubyの標準添付のライブラリでDigest認証に対応しているものはないようです。

 [続きを読む...]
Category: Tips | / / | Comment(0) | TrackBack(0) | Permalink |
2009/12/08
[ by hsur at 23:23]

irbでコード補完

 

irbはちょっとしたコードの実行を確認するときにとても便利ですが、それをさらに便利にするtipsがRuby Advent Calendar jp: 2009 : ATNDにに載っていたのでメモ。

irb を快適に使うための Tips - まさにっき(コードで世界を変えたい人の記録)

まとめると
* よく使うライブラリは requier しておくと良いよ
* Wirble 入れると色付きや補完機能が有効になるよ
* でも Windows では色がつかないよ(追記に記載したとおり、win32console を入れると色が付きます!)
* 色の表示意外に目当てがなければ、Wirble は必要ないよ
* 補完と履歴は require 'irb/completion' と IRB.conf[:SAVE_HISTORY] = 100000 で十分だよ

これまで散々世話になってきたのに~/.irbrcに設定が書いておけたり、コード補完ができたりするのは知りませんでした。普段からEclipseに慣れているせいか、名前の長いメソッドをフルに打つのがものすごく嫌だったんですが、これでこの重圧から解放されそうです。

 [続きを読む...]
Category: Tips | | Comment(0) | TrackBack(0) | Permalink |
«Prev || 1 · 2 · 3 · 4 · 5 · 6 · | Next»
» ArchiveList
Home (Tag for "ruby")