続き。
上記質問で大変お世話になりました。助かりました。
RubyでSqlite3に書き込む方法や分岐に関して、自分でも調べ直して、いろいろ試していますがうまくいかないので教えて頂きたいです。
1. '停電履歴情報はありません。'の際には書き込まない方にしたいのですがif分岐でエラーないのにうまくできないという、、
NULLやNILや当てはまらない逆の条件なども試したのですが。どうしても書き込まれてしまうというorz
2.URLの範囲で複数のページをそのまま認識しているのですが、この場合で短い書き方はどうすればいいのかがわかりません。
day060-j.htmlなどで、数字だけ連番で変えていきたいのですが。
Rubyにはインクリメントデクリメントがないらしいですが、for文でエラーでないのですがやはり結果として書き込まれない状態になりまして。
もしわかれば教えて頂きたいです。よろしくお願いします。
1. '停電履歴情報はありません。'の際には書き込まない方にしたいのですがif分岐でエラーないのにうまくできないという、、
NULLやNILや当てはまらない逆の条件なども試したのですが。どうしても書き込まれてしまうというorz
抽出のスクリプトが http://q.hatena.ne.jp/1441975146#a1251552 のコードだとして、こんな感じで大丈夫でしたけど...
def treat_data data if data[0] == "停電履歴情報はありません。" then return end db = SQLite3::Database.new("test.sqlite") db.transaction ...
Ruby のバージョンによりますが、よほど古いものを使っていなければ、スクリプトの文字コードが UTF-8 じゃないとエラーになります。
条件を判定しているところで文字を表示して、意図通りに判定できているのか、確認をしてみたら良いと思います。
def treat_data data if data[0] == "停電履歴情報はありません。" then puts "× 停電なし" # ★ここ return end puts "○ 停電あり" # ★ここ db = SQLite3::Database.new("test.sqlite") db.transaction ...
2.URLの範囲で複数のページをそのまま認識しているのですが、この場合で短い書き方はどうすればいいのかがわかりません。
ループの回し方は色々ありますが、例えば、こんな感じでいけます。
# 1 から 5 まで (1..5).each { |i| uri = "http://teideninfo.tepco.co.jp/day/day#{sprintf("%03d",i)}-j.html" open(uri, http_options){ |io| txt = io.read } ... }
頭にゼロをつけて 3ケタにするには、sprintf を使います。
http://docs.ruby-lang.org/ja/2.0.0/doc/print_format.html
当日だけは URL がちょっと変わるので、もし、当日も含めたければこんな感じ。
# 0 から 5 まで (0..5).each { |i| if i == 0 then uri = "http://teideninfo.tepco.co.jp/day/index-j.html" # ゼロは当日 else uri = "http://teideninfo.tepco.co.jp/day/day#{sprintf("%03d",i)}-j.html" end open(uri, http_options){ |io| txt = io.read } ...
ゼロ始まりのループだと、こういうふうにも書けます。
# 0 から 5 まで(6 までじゃない) 6.times { |i| ...
require 'open-uri' require 'sqlite3' class RowData def initialize @first_line_mode_ = true @data_ = [] @rows_ = [] end def push data, rows if @first_line_mode_ then @data_ << data @rows_ << rows else i = @data_.index(nil) @data_[i] = data @rows_[i] += rows end end def clear is_remain = false (0...@data_.length).each { |i| @rows_[i] -= 1 if @rows_[i] == 0 then @data_[i] = nil else is_remain = true end } unless is_remain then @data_ = [] @rows_ = [] @first_line_mode_ = true else @first_line_mode_ = false end end def to_a @data_.dup end def empty? @data_.empty? end end def treat_data data puts data if data[0] == "停電履歴情報はありません。" then return end db = SQLite3::Database.new("test.sqlite") db.transaction # 1カラム目は、<BR> で分離 t = data[0].split /<BR>/i blackout_time = t[0] recover_time = t[1] # 残りはそのまま保存する pref = data[1] city = data[2] area = data[3] blackout_count = data[4] blackout_reason = data[5] update_time = data[6] sql = 'insert into TEPCO(blackout_time, recover_time, pref, city, area, blackout_count, blackout_reason, update_time) values (?, ?, ?, ?, ?, ?, ?, ?);' db.execute(sql, [blackout_time, recover_time, pref, city, area, blackout_count, blackout_reason, update_time]) db.commit db.close end def extract_blackout_information(uri) # get HTML txt = "" http_options = {} open(uri, http_options){ |io| txt = io.read } # encode to UTF-8 txt.force_encoding("Shift_JIS") txt = txt.encode("UTF-8") data = RowData.new txt.each_line { |line| line.chomp! if line =~ %r|<td([^>]+)>(.*)</td>| then td_attr = $1 txt = $2 rowspan = 1 if td_attr =~ %r|rowspan="(\d+)"| then rowspan = $1.to_i end data.push txt, rowspan elsif line =~ %r|</tr>| then unless data.empty? then treat_data data.to_a end data.clear end } end # 本日 extract_blackout_information("http://teideninfo.tepco.co.jp/day/index-j.html") # 本日以前 (1..7).each { |i| extract_blackout_information("http://teideninfo.tepco.co.jp/day/day#{sprintf("%03d",i)}-j.html") }
コードを移動してるので単純にテキスト比較だと随分変わっているように見えますが、それほど大きな変更はしていません。
ログを取る、というのは面白いですね。
2016/02/24 17:40:11そちらでは例えば毎日の処理でそれぞれログ、という発想で重複しているとかは普通は気にしないものでしょうか。
表示しない分をログに渡すだと、データベースに記載する分もそちらに渡して記録するような印象で話しています。
数日おきにチェックすればいいとはいえ、本来ならちゃんと処理されたかを何かわかるように知らせる方がこういう時にはいいのかな。
どうせそっちでも確認してチェックなのだから結局同じなのですがw
普通のロギングのライブラリだと、メッセージ毎にレベルがあります。
2016/02/24 21:05:06だいたい、デバッグ、情報、警告、エラー、致命的、くらいな。
前の質問の回答とかではエラー処理を端折ってますけれど、エラーが起きたらエラーレベルでメッセージを残す。
「正常に終了した」だと、情報レベルでメッセージを残す。
情報レベル以下をロギングしないように設定するか、ロギングはするけど日々の確認では見ない(意識として、と、仕組みとして、のふたつあります)か、というような感じです。