04/02
Thu
2009
scRUBYt!を使ったスクレイピングの練習に複数のニュースサイトから最新ニュースを集めて
表示するサンプルアプリを作った。
scRUBYt!,REXMLとも適当なドキュメントが見つからず苦労した。
[環境]
VMware Server 2.0.0
Fedora 10
Apache 2.2.10
ruby 1.8.6
scrubyt 0.3.4
・XPath
scRUBYTt!でXPathの指定が期待通り動かず手間取った。
私がXPathをよくわかっていないことも原因だろうと思うが、
「:example_type => :xpath」をつけないとちゃんと動かない(?)との
情報もあり。(http://d.hatena.ne.jp/kasei_san/20090204/p1)
・参考ドキュメント
scRUBYt!
http://github.com/scrubber/scrubyt_examples/tree/master
→scRUBYt!のサンプル。
REXML
http://www.germane-software.com/software/rexml/docs/tutorial.html
→はじめの方にある「Accessing Elements」は参考になった。
http://pub.cozmixng.org/~kou/rexml-doc-ja/
→それっぽいClass,Methodを感で使ってみた。
・データの扱い
scRUBYt!のto_hash関数でHASHオブジェクトにして扱おうと思ったが
うまくいかなかった。入力データの構造に縛りがあるのだろうか。
to_xmlで出力し、REXMLオブジェクトに入れて扱う。
#!/usr/bin/env ruby
ENV['INLINEDIR']='/tmp/.ruby_inline' #RubyInlineのバグ(?)対策
require 'rexml/document'
require 'rubygems'
require 'scrubyt'
require 'kconv'
#Cnet
data1 = Scrubyt::Extractor.define do
fetch 'http://japan.cnet.com/'
record "//div[@class='section08 articlelist08']" do
link_title "//li/a", :write_text=>true do
link_url
end
end
end
xml1 = REXML::Document.new data1.to_xml
#ITPro
data2 = Scrubyt::Extractor.define do
fetch 'http://itpro.nikkeibp.co.jp/news/index.html'
record "//div[@class='newsPickup']" do
link_title "//div/span/a", :write_text=>true do
link_url
end
end
end
xml2 = REXML::Document.new data2.to_xml
#CodeZine
data3 = Scrubyt::Extractor.define do
fetch 'http://codezine.jp/'
record "//div[@id='news_list']" do
link_title "//li/a", :write_text=>true do
link_url
end
end
end
xml3 = REXML::Document.new data3.to_xml
title="News-Search | 複数のニュースサイトから最新ニュースをスクレイピング"
#以下、表示部
print <<"EOS"
Content-type: text/html; charset=shift_jis\n\n
<html>
<head>
<title>#{title}</title>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">
<style type="text/css">
td {border:1px black solid;vertical-align:top;}
.yellow {background-color:yellow;}
.blue {background-color:blue;}
.green {background-color:green;}
</style>
</head>
<body>
<h1>#{title}</h1>
<table style="border:1px black solid;">
<tr>
<td class="yellow">CNET</td>
<td class="blue">ITPro</td>
<td class="green">CodeZine</td>
</tr>
<tr>
<td>
EOS
xml1.elements.each("//link_title"){
|element|
puts "<a target='_blank' href=#{element.get_text('link_url')}>#{element.text}</a><br>\n"
}
print <<"EOS"
</td>
<td>
EOS
xml2.elements.each("//link_title"){
|element|
puts "<a target='_blank' href='http://itpro.nikkeibp.co.jp#{element.get_text('link_url')}'>#{element.text.tosjis}</a><br>\n"
}
print <<"EOS"
</td>
<td>
EOS
xml3.elements.each("//link_title"){
|element|
puts "<a target='_blank' href='http://codezine.jp/#{element.get_text('link_url')}'>#{element.text.tosjis}</a><br>\n"
}
print <<"EOS"
</td>
</tr>
</table>
</body>
</html>
EOS
03/29
Sun
2009
Apaacheがシステムの起動時に自動的に起動するように設定しようとしたら、
結構手こずったのでメモ。
[環境]
VMware Server 2.0.0
Fedora 10
Apache 2.2.10
・起動スクリプトは既にあった。
/etc/rc/init.d/httpd
---------------------------------------------------------------------------------------------
#!/bin/bash
#
# httpd Startup script for the Apache HTTP Server
#
# chkconfig: - 85 15
# description: The Apache HTTP Server is an efficient and extensible \
# server implementing the current HTTP standards.
(以下略)
---------------------------------------------------------------------------------------------
「# chkconfig: - 85 15」 が [起動レベル 起動順番 停止順番]になっている模様。
起動レベルが「-」なので起動しない。ランレベル3,5で起動するように
# chkconfig: 35 85 15 に変更
[root@VMware1 ~]# chkconfig --add httpd
[root@VMware1 ~]# chkconfig --list httpd
httpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
→設定が反映されない。さっき修正した箇所が参照されているかどうかを確認するために、
# chkconfig: 35 85 16 に変更してもう一度。
[root@VMware1 ~]# chkconfig --add httpd
[root@VMware1 ~]# chkconfig --list httpd
httpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
[root@VMware1 ~]# ls -l /etc/rc3.d/*httpd
lrwxrwxrwx 1 root root 15 2009-03-29 13:23 /etc/rc3.d/K16httpd -> ../init.d/httpd
→やはり起動設定はできていないが、停止のためのシンボリックリンクは16になっているので
修正した箇所が参照はされている模様。いろいろ試したがchkconfig --addでは起動設定できなかった。
・chkconfigコマンドでレベルを指定し直接設定
[root@VMware1 ~]# chkconfig --level 35 httpd on
[root@VMware1 ~]# chkconfig --list httpd
httpd 0:off 1:off 2:off 3:on 4:off 5:on 6:off
→設定できている。
・システムをシャットダウンから起動。
[root@VMware1 ~]# service httpd status
httpd (pid 2164) を実行中...
→Apacheも起動してる。OK。rebootでも確認できた。
起動スクリプトの記述で起動設定できない理由は不明。。
VMだから?
03/28
Sat
2009
scRUBYt!のサンプルプログラムebay.rbをブラウザからアクセスして動かしてみる。
手こずったがなんとか動くようになったので作業ログ。
Webアプリにするときは表示出力部分を整えないといけない。
[環境]
VMware Server 2.0.0
Fedora 10
Apache 2.2.10
scRUBYt!-0.3.4
RubyInline-3.6.3
・とりあえずブラウザからアクセスしてみるが、500エラーになる。
Apacheのerror_logを見てみるとエラーが出力されている。
[Sat Mar 28 13:08:08 2009] [error] [client 192.168.1.2] Define INLINEDIR or HOME in your environment and try again
[Sat Mar 28 13:08:08 2009] [error] [client 192.168.1.2]
[Sat Mar 28 13:08:08 2009] [error] [client 192.168.1.2] Premature end of script headers: ebay.rb
調べてみると、「Define INLINEDIR or HOME in your environment and try again」はRubyInline-3.6.3のバグの模様。
3.6.3より上のバージョンに代えようとしたが、scRUBYt!-0.3.4はRubyInline-3.6.3が必須。scRUBYt!の0.4.1以上はfirewatirをrequireするのでパスしたい。現状の構成でエラーを解決することにする。
「Define INLINEDIR or HOME in your environment and try again」はRubyInlineが環境変数$HOME,$INLINEDIRのいずれかを参照しようとして、どちらも参照できない場合に起こる模様。(コマンドプロンプトで直接たたく際は$HOMEがあるが、Webサーバ経由で実行だとapacheユーザーになるため。)
・ebay.rbに、
ENV['INLINEDIR']=/tmp/.ruby_inline (※1)
を追記し、環境変数INLINEDIRが参照できるように修正しコマンドラインから実行。
→下記エラーが発生
[root@VMware1 goy]# /var/www/cgi-test/ebay.rb
/tmp/.ruby_inline is insecure (40777). It may not be group or world writable. Exiting.
・INLINEDIRに割り当てているフォルダのパーミッションを変更。
chmod -R 0755 /tmp/.ruby_inline
コマンドラインから実行→OK
ブラウザから実行→500エラー error_logに下記が出力される。
[Sat Mar 28 16:34:30 2009] [error] [client 192.168.1.2] /usr/lib/ruby/gems/1.8/gems/scrubyt-0.3.4/lib/scrubyt/core/scraping/filters/text_filter.rb:25: warning: don't put space before argument parentheses
[Sat Mar 28 16:34:41 2009] [error] [client 192.168.1.2] malformed header from script. Bad header=<root>: ebay.rb
・http応答ヘッダーでContent-Typeを指定するよう追記(※2)
ブラウザから実行→OK!
最終的にソースは下記のように。
--------------------------------------------------------
[root@VMware1 cgi-test]# vi ebay.rb
#!/usr/bin/ruby -K
ENV['INLINEDIR']='/tmp/.ruby_inline' # ←※1
require 'rubygems'
require 'scrubyt'
ebay_data = Scrubyt::Extractor.define do
fetch 'http://www.ebay.com/'
fill_textfield 'satitle', 'ipod'
submit
record "//table[@class='nol']" do
name "//td[@class='details']/div/a"
end
end
print "Content-type: text/html\n\n" # ←※2
puts ebay_data.to_xml
---------------------------------------------------------
~
03/27
Fri
2009
03/21
Sat
2009
http://github.com/scrubber/scrubyt_examples/tree/master
にあるサンプル、ebay.rbを動かす。
(最新のscRUBYt!をgemで依存関係を解決して淹れるだけだと
動かなかったので、苦戦。散々苦戦。)
○環境
VMware Server 2.0.0
Fedora 10
○結果
パッケージを下記のバージョンにすると動いた。
scRUBYt! 0.3.4
Hpricot 0.6
Mechanize 0.6.5
○詳細
●agent
http://scrubyt.org/blog/installing-firewatir-for-firefox-30/
のResponsによると、firefox2が必要なのはfirefoxをagentとする
firescRUBYt!を使う場合で、scRUBYt!はdefaultでMechanizeをangentとするらしい。
scRUBYtの0.4.1以上ではagentとしてfirefoxを使うようだ。
scRUBYt(>=0.4.1)を使おうとすると、firewatirを求めるエラーがでる。
[root@VMware1 cgi-test]# ./ebay.rb
/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- firewatir (LoadError)
from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from /usr/lib/ruby/gems/1.8/gems/scrubyt-0.4.1/lib/scrubyt/core/navigation/agents/firewatir.rb:2
from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from /usr/lib/ruby/gems/1.8/gems/scrubyt-0.4.1/lib/scrubyt.rb:29
from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `gem_original_require'
from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `require'
from ./ebay.rb:4
「scRUBYt! 0.3.4ではfirefoxを使わずに動いている」 ととれる投稿が
あったので、scRUBYt!の0.3.4を指定してインストールする。
サンプルを実行すると、scRUBYt!の0.4.06のときのようなfirewatir関係の
エラーはでなくなった。
●依存関係
http://scrubyt.org/download.html によると、
>scRUBYt!のインストールは非常に簡単で下記を実行するだけ
>sudo gem install hpricot
>sudo gem install mechanize
>sudo gem install scrubyt
とのことだが、これだと各パッケージの最新が入ってしまいうまう。
http://wiki.scrubyt.org/index.php?title=Installation_Instructions にあるように、
Hpricot 0.6, Mchanize 0.6.5を指定してインストール。
●実行
以上の環境にすると動いた!
はじめに警告がでてるけど、まぁ大丈夫か。
[root@VMware1 cgi-test]# ./ebay.rb
/usr/lib/ruby/gems/1.8/gems/scrubyt-0.3.4/lib/scrubyt/core/scraping/filters/text_filter.rb:25: warning: don't put space before argument parentheses
http://shop.ebay.com/items/_W0QQ_nkwZipodQQ_armrsZ1QQ_fromZR40QQ_mdoZ
<root>
<record>
<name>Original Earphone Headphone for i Pod iPhone Nano TouchHIGH QUALITY*POWERSELLER*30 DAY GUARANTEE*IN STOCK$6.49Free shipping20d&#160;3h&#160;26m</name>
</record>
<record>
<name>EnlargeGriffin iTrip LCD FM Transmitter for iPod White NEW WBRAND NEW, FULL RETAIL PACKAGE, GREAT FOR GIFT GIVING!$9.9924d&#160;14h&#160;21m</name>
</record>
<record>
<name>EnlargeLeather Case Pouch For Apple iPod i Touch 8GB 16GB 32GBGlobally Ranked #3 eBay Power Seller *FREE SHIPPING*$6.99Free shipping1d&#160;21h&#160;50m</name>
</record>
<record>
<name>APPLE IPOD TOUCH 8GB VIDEO WiFi MP3 PLAYER 8 GB Grade AFree Ship, 90 Day Warranty, Newest Model in Retail Box16 Bids$180.00Free shipping46m</name>
</record>
<record>
(省略)
ようやくうごいた~、いやん♪
これからいろいろ使ってみよう。