質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

3回答

4778閲覧

RubyによるWebスクレイピングでの404エラー対策

mycee0001

総合スコア16

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

2クリップ

投稿2015/11/09 01:32

RubyにてWebスクレイピングをおこないたいと思っております。
対象のURLは末尾の7桁の数字を変更して、変更した先のh2要素を抜くというものです。
初回のアクセス時にbasic認証があり、mechanizeで対策をしたのですが(以下コード)
現在問題点は2つございます。
①unexpected end of input errorが起きているが場所がわからない
②mechanizeの書き方が間違っていないか?
ご教示いただけると幸いです

require './Loader.rb' require 'open-uri' require 'openssl' require 'nokogiri' require 'mechanize' test = Loader.new test.loading agent = WWW::Mechanize.new{|a| a.log=Logger.new('access.log')} agent.verify_mode = OpenSSL::SSL::VERIFY_NONE agent.user_agent = 'Windows IE11' agent.add_auth("URLパス", 'ユーザー名', 'パスワード') url = "対象URL" $arry.each do $num charset = nil begin html = open(agent.get(url)) do |f| charset = f.charset f.read rescue Timeout::Error puts "caught Timeout::Error!" retry # タイムアウト用 rescue WWW::Mechanize::ResponseCodeError => e case e.response_code when "404" puts "caught Net::HTTPNotFound!" next # 404用 when "502" puts "caught Net::HTTPBadGateway!" retry # 502用 else puts "caught Excepcion!" + e.response_code retry end doc = Nokogiri::HTML.parse(html, nil, charset) doc.xpath('//div[@id="main"]/h2').each do |node| p node end end

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

  • エラーに関して: ruby -c file_name.rb で構文チェックを走らせるとわかりやすいです
  • $arry.each に処理を詰め込みすぎています 処理のグループ分け(名前付け)をして、関数に切り出しましょう
  • グローバル変数の利用は避け、そういったシーンではクラスを定義してその中でインスタンス変数を利用するとよいかもしれません
  • if と同様に、do...end もネストを深くしないよう関数に切り出すなどで浅く保つ

まずは見易いコードに整え、そのあとで構文エラーに対応しても遅くはないと思います


生の処理を関数に換える

例外が発生する処理も、yield を利用すると関数として切り出すことができるとおもいます

例:

ruby

1def calc 2 yield 3rescue ZeroDivisionError => e 4 puts e.message 5end 6 7puts calc { 1 + 1 } # => 2 8puts calc { 0 / 0 } # => divided by 0

Mechanize の初期化:

ruby

1def mechanize_agent 2 agent = WWW::Mechanize.new { |a| a.log = Logger.new('access.log') } 3 agent.verify_mode = OpenSSL::SSL::VERIFY_NONE 4 agent.user_agent = 'Windows IE11' 5 agent.add_auth('URLパス', 'ユーザー名', 'パスワード') 6 agent 7end

このように関数として切り出していくと、構文エラーの発生しにくいコードにしていくことができるのではないでしょうか

何か参考になれば幸いです

Links

投稿2015/11/09 04:00

編集2015/11/09 04:30
gouf

総合スコア2321

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mycee0001

2015/11/09 04:19

@gouf様 的確なアドバイスありがとうございます。まずは頭の整理ふくめて、関数単位の切出しやってみます
guest

0

他の方が指摘されているようにbegin内の
html = open(agent.get(url)) do |f|
に対してendが無いように見受けられます。

私も初心者で
やりたいことに合致するかわかりませんが、
下記のようにしてみてはいかがでしょうか?

ruby

1 begin 2 page = agent.get(url) 3 rescue Timeout::Error 4 puts "caught Timeout::Error!" 5 retry # タイムアウト用 6 rescue Mechanize::ResponseCodeError => e 7 case e.response_code 8 when "404" 9 puts "caught Net::HTTPNotFound!" 10 when "502" 11 puts "caught Net::HTTPBadGateway!" 12 retry # 502用 13 else 14 puts "caught Excepcion!" + e.response_code 15 retry 16 end 17 end

お役に立てれば幸いです。

投稿2017/07/09 08:13

編集2017/07/09 08:23
black-bass

総合スコア10

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

  1. インデント(段下げ)がでたらめになっているのは自覚されていますか?

インデントを正しくすれば、endの抜けに気づけると思います。二カ所ですね。
インデントを全くしないのでもなく、でたらめにするというのは、何故なんですかね?

  1. $arry や $num は、Loader.rb で定義されているのだと思いますが、グローバル変数経由以外の方法がおそらくとれると思います。

  2. $num が意味不明に置かれています。

  3. リトライしても又同じエラーになりそうな気がしますけど。

  4. each ループ内にこれくらいの機能の処理を書くのは良いと思いますが、エラー処理が混ざっているのが見にくいですね。aget.getに一皮かぶせたメソッドを作って、その中でエラー処理をするのがいいように思います。

  5. require './Loader.rb' は、「実行時のカレントディレクトリにあるLoader.rb」を読み込みますが、意図と合っていますか?「このスクリプトと同じディレクトリにあるLoader.rb」の場合は、require_relative 'Loader.rb' です。

投稿2015/11/09 12:54

otn

総合スコア84533

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問