質問: 情報元の仕様が変わりエラーとなったスクレイピングを再度動かせるようにして欲しい。Ruby。 久しく質問させて頂きます。 以下関係する過去の質問。 リンク先でも表記され下に行くほど古い質問です。 関連するURL。 最近エラーを出すようになりご相談させて頂きたいです。 というのも元の仕様が変わったためで、日付が変わるごとにURLもカウントアップし日付ごとのURLでそれぞれ結果を表示していた仕様が、日付選択後も同一のURLでそれぞれ日付ごとの結果を表示する仕様になったためです。 この場合、どのようにスクレイピングすれば良いのだろう?とお教え頂きたいです。 今回のエラー結果は質問本文が500文字以内のためここに書けず、画像添付します。 必要であれば実行ファイルも添付します。 お手間おかけしますが、 どうぞよろしくお願いします。
回答: 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分未満の停電の二つがあるのですが区別していません。