人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

情報元の仕様が変わりエラーとなったスクレイピングを再度動かせるようにして欲しい。Ruby。

久しく質問させて頂きます。
以下関係する過去の質問。
リンク先でも表記され下に行くほど古い質問です。
https://q.hatena.ne.jp/1473168239
https://q.hatena.ne.jp/1455811321
https://q.hatena.ne.jp/1443599941
https://q.hatena.ne.jp/1441975146
https://q.hatena.ne.jp/1434818671
http://q.hatena.ne.jp/1436077068

関連するURL。
https://teideninfo.tepco.co.jp/day/teiden/index-j.html
https://teideninfo.tepco.co.jp/day/shuntei/index-j.html

最近エラーを出すようになりご相談させて頂きたいです。
というのも元の仕様が変わったためで、日付が変わるごとにURLもカウントアップし日付ごとのURLでそれぞれ結果を表示していた仕様が、日付選択後も同一のURLでそれぞれ日付ごとの結果を表示する仕様になったためです。
この場合、どのようにスクレイピングすれば良いのだろう?とお教え頂きたいです。
今回のエラー結果は質問本文が500文字以内のためここに書けず、画像添付します。
必要であれば実行ファイルも添付します。
お手間おかけしますが、
どうぞよろしくお願いします。

1586292241
●拡大する

●質問者: FREEz
●カテゴリ:インターネット ウェブ制作
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● tobeoscontinue
●2000ポイント ベストアンサー

XMLファイルが準備されたようでindex.htmlからjavascriptを使ってXMLファイルを読み込み表示をしているようです。
直接XMLファイルを読み込むことでhtmlをパースするよりは楽になりました。
XMLファイルはindex-j.htmlがindex-j.xmlとなっています。ファイルは日付ではなく当日、前日、前々日となっていて60日分は遡れるようです。

nokogiriが何故かダメだったので今回はrexmlです。

require "rexml/document"
require "open-uri"

def tepco_cache(path, day='index')
 cache_file = path+'-'+day+'-j.xml'
 file_path = File.exist?(cache_file) ? cache_file : "https://teideninfo.tepco.co.jp/day/"+path+"/"+day+"-j.xml"
 xml = open(file_path).read
 open(cache_file, 'w').write(xml) if file_path[0] == 'h'
 return xml
end

# def tepco_cache(path, day='index')
# open("https://teideninfo.tepco.co.jp/day/"+path+"/"+day+"-j.xml").read
# end

def tepco_csv(xml)
 doc = REXML::Document.new(xml)
 doc.get_elements('//データ部').map do |e| 
   def e.gets_text(name)
   get_elements('./'+name).map {|c| c.text }.join('|')
   end
   [ e.gets_text('発生日時'),    # 発生日時
   e.gets_text('復旧日時'),          # 復旧日時
   e.gets_text('都県部/都県名'),          # 都県名
   e.gets_text('都県部/市区町村部/市区町村名'),   # 市区町村名
  e.gets_text('都県部/市区町村部/地区部/地区名'),  # 地区名
  e.gets_text('停電軒数'),# 停電軒数
   e.gets_text('停電理由'),# 停電理由
   e.gets_text('更新日時') ].join(',') if e.has_text? # 更新日時
 end.join("\n")
end

print tepco_csv(tepco_cache("teiden"))
print tepco_csv(tepco_cache("shuntei"))

tepco_cacheは一度ネットから落としたら次回はローカルから読み込むためのものです。そんなもの必要ないというのであれば注釈にあるように変更すれば毎回ネットから落とせます。日付が変わってもファイル名は同じなので新しい日付の場合はファイルを消すか移動させてください。

tepco_csvはxmlファイルを読み込んでcsvの文字列で返します。
市区町村名、地区名は複数あるので|で区切っています。
一つしか無い場合はget_textでいいのですが復旧日時など無い場合にエラーが出るので助長ですがgets_textにしています。
if e.has_text? は4/11のようにデータ部の中身が無い場合の対処でこれが無いと
,,,,,,,,のようなcsv文字列が返ることになります。
データ部は5分以上の停電と自動復旧等による5分未満の停電の二つがあるのですが区別していません。


FREEzさんのコメント
エラーになりました。 rexmlの使用に関して調べましたがライブラリが要るわけではありませんし、構文エラーを見ていますが何だろうな。 訂正がいるように見えないので。 もし分かれば教えてください。 ローカルにキャッシュファイルを保存しておく考えは負荷軽減にもなりますし面白いです。 ただオリジナルが後々でデータを変更すると気付かないので、やはりチェックするしかないんじゃないかなと思いました。 例えば、停電原因の古い訂正や不明分となっていたものに原因判明もあるので。 データ部は5分以上の停電と自動復旧等による5分未満の停電の区別は不要なので助かります。 C:\Users>ruby tepco-kaizen.rb tepco-kaizen.rb:23: syntax error, unexpected tIDENTIFIER, expecting ']' 縲? e.gets_text('蠕ゥ譌ァ譌・譎・... ^ tepco-kaizen.rb:28: syntax error, unexpected tIDENTIFIER, expecting keyword_do or '{' or '(' 縲? e.gets_text('蛛憺崕逅・罰'), # 蛛憺崕逅・罰 ^ tepco-kaizen.rb:28: syntax error, unexpected ',', expecting keyword_end 縲? e.gets_text('蛛憺崕逅・罰'), # 蛛憺崕逅・罰 ^ tepco-kaizen.rb:29: syntax error, unexpected ']', expecting keyword_end ... e.gets_text('譖エ譁ー譌・譎・) ].join(',') if e.has_text? # ... ...

tobeoscontinueさんのコメント
キャッシュについては岡崎図書館事件を懸念してのことでした。 引数に-newを付加した場合はファイルを削除するというのを追加してみてはどうでしょう。 ARGV.each {|pm| Dir.glob("*-index-j.xml") {|f| File.delete(f) } if pm == '-new' } エラーについては全角スペースが含まれていたためで半角スペースに全置換して下さい。 SSL_connectのエラーが発生するようでしたら https://qiita.com/whiteleaf7@github/items/4504b208ad2eec1f9357 にあるようにローカルに証明書をダウンロードし環境変数を設定することで回避できると思います。 編集しようと思って削除してしまったorzので再投稿。

FREEzさんのコメント
動かせました。。ただ本日分しか動いていない、、 xmlのリスト見たら1ヶ月分ありますね。 読み取って遡るようにしないといけないわけか、、 時間ないなどうしよう、、 前のやつに追加・改変して動くかな。

tobeoscontinueさんのコメント
前日分などはindexがday001と変わるだけなので print tepco_csv(tepco_cache("teiden", "day001")) とすると前日分が処理されます。 面倒なら 1.upto(60) {|num| days = "day#{'%03d' % num}" print tepco_csv(tepco_cache("teiden", days)) print tepco_csv(tepco_cache("shuntei", days)) } で1から60まで処理します。

FREEzさんのコメント
動かせました、ありがとうございます。 後は前のと合わせてデータベースに上書きしていきたいと思います。 つかぬことを伺いますが、 今回どのようにxmlファイルの方に気付いたのでしょうか。 RSSなどでxmlファイルを別に置くことはむしろ普通ですが、気付かなかったのでどのように辿り着いたのだろうかと。単純に見逃していただけだったら申し訳ないのですが。

FREEzさんのコメント
ちょっと大変だけど頑張ってみます。ありがとうございました。

tobeoscontinueさんのコメント
元の仕様が変わったとあったので先ずは普通にindex.htmlにアクセスしてどんな感じか見ました。 次にindex.htmlをソースで見てデータの数値がどうなっているかを探してみましたが 該当する文字列が無いためjavascriptを使っているのだろうと考えました。 しかしそれらしいコードも無いのでそれらしい.jsファイルが無いかと見てみました。 そのどれかのファイルでindex-j.htmlにアクセスしていると思ったのですがそのファイルを 探せませんでした。何か勘違いしているのかもしれません。 index.htmlで『停電発生年月日を選択してください。』のプルダウンメニューを右クリックして、 出てくるポップアップメニューの検証を選択して<option>のvalueから間接的にファイル名を知ることはできるのですが、それがファイル名だという説明にはなってませんが。

FREEzさんのコメント
なるほど、今回動かしてxmlで読み込んだ後にできたアクセス負荷軽減のための一時ファイルを見ると公開されている形式そのままで見ることができるため、この形式のままどこかアクセスできるのかとも思いましたが、分からなかったので。

tobeoscontinueさんのコメント
バグが見つかってしまいました。すいませんorz。 現象は市区町村名が複数ある場合に地区名がどちらに対応しているのかわからないというものです。 5/20のファイルでは早川町と身延町があるのですが地区名が 雨畑|大島|榑坪|高住|笹走|塩之上|千須和|初鹿島|保|薬袋|粟倉|江尻窪|遅沢|中山|梨子|平須|福原|古長谷|身延七面山参道|身延|矢細工 となり区切りがわかりません。そこで市区町村名/地区名と前に市区町村名を付加し 早川町/雨畑|早川町/大島|早川町/榑坪|早川町/高住|早川町/笹走|早川町/塩之上|早川 町/千須和|早川町/初鹿島|早川町/保|早川町/薬袋|身延町/粟倉|身延町/江尻窪|身延町/遅沢|身延町/中山|身延町/梨子|身延町/平須|身延町/福原| 身延町/古長谷|身延町/身延七面山参道|身延町/身延|身延町/矢細工 と修正します。新たにchiq_textを追加しました。 def tepco_csv(xml) doc = REXML::Document.new(xml) doc.get_elements('//データ部').map do |e| def e.gets_text(name) get_elements('./'+name).map {|c| c.text }.join('|') end def e.chiq_text(name) get_elements('./'+name).map {|c| c.get_elements('../../市区町村名')[0].text+'/'+c.text }.join('|') end [ e.gets_text('発生日時'),# 発生日時> e.gets_text('復旧日時'), # 復旧日時> e.gets_text('都県部/都県名'), # 都県名> e.gets_text('都県部/市区町村部/市区町村名'), # 市区町村名> e.chiq_text('都県部/市区町村部/地区部/地区名'), # 地区名> e.gets_text('停電軒数'),# 停電軒数> e.gets_text('停電理由'),# 停電理由> e.gets_text('更新日時') ].join(',') if e.has_text? # 更新日時> end.join("\n") end

FREEzさんのコメント
わざわざありがとうございます。確認しました。。

2 ● chsm
●0ポイント

見れているように見えますが。


質問者から

ご回答ありがとうございます。大変助かります。

また申し訳なかったです。お待たせいたしました。
WindowsUPDATEによる異常、回復できず故障、からようやく戻すことができました。
至急見させて頂きます。
が、朝早くて夜に対応できていないので、明日また、、



●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ