2017-09-04 13 views
0

私は、複数のサブディレクトリのjsonページをリクエストし、大学プロジェクトの各ページのタイトルとリンクを取得しようとしています。問題のコードは次のとおりです。reddit apiを解析するときの未定義のメソッド[] "

require 'rufus-scheduler' 
require 'json' 
require 'httparty' 
ENV['TZ'] = 'Europe/Dublin' 

scheduler = Rufus::Scheduler::singleton 


scheduler.every '12h00m', :first_at => Time.now + 10 do 

array_of_subreddits = ["pics", "memes", "funny", "aww", "memes", 
"birdswitharms"] 
array_of_subreddits.each do |category| 
sleep 10 #wait 10 seconds between each request 

@response = JSON.parse(HTTParty.get("http://reddit.com/r/#{category}/.json?limit=25").body) 

    @response['data']['children'].each do |data| 
     @link = data['data']['url'] 
     @title = data['data']['title'] 
     @category = category 
     Pic.create([{:title => "#{@title}", :link => "#{@link}", :category => "#{@category}"}]) 
    end 
    end 
end 

これは完全に動作することがあります。 1または2回通過した後、後に、より頻繁にではないが、それは私にこのメッセージを与えるより:

NoMethodError (undefined method `[]' for nil:NilClass): 
 
    app/controllers/home_controller.rb:17:in `block in index' 
 
    app/controllers/home_controller.rb:9:in `each' 
 
    app/controllers/home_controller.rb:9:in `index' 
 

 

 
    Rendered /Users/conorbreen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_source.erb (4.8ms) 
 
    Rendered /Users/conorbreen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.2ms) 
 
    Rendered /Users/conorbreen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.2ms) 
 
    Rendered /Users/conorbreen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (66.2ms) 
 
    Rendered /Users/conorbreen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/web-console-2.3.0/lib/web_console/templates/_markup.html.erb (0.4ms) 
 
    Rendered /Users/conorbreen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/web-console-2.3.0/lib/web_console/templates/_inner_console_markup.html.erb within layouts/inlined_string (0.3ms) 
 
    Rendered /Users/conorbreen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/web-console-2.3.0/lib/web_console/templates/_prompt_box_markup.html.erb within layouts/inlined_string (0.3ms) 
 
    Rendered /Users/conorbreen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/web-console-2.3.0/lib/web_console/templates/style.css.erb within layouts/inlined_string (0.5ms) 
 
    Rendered /Users/conorbreen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/web-console-2.3.0/lib/web_console/templates/console.js.erb within layouts/javascript (51.6ms) 
 
    Rendered /Users/conorbreen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/web-console-2.3.0/lib/web_console/templates/main.js.erb within layouts/javascript (0.3ms) 
 
    Rendered /Users/conorbreen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/web-console-2.3.0/lib/web_console/templates/error_page.js.erb within layouts/javascript (0.5ms) 
 
    Rendered /Users/conorbreen/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/web-console-2.3.0/lib/web_console/templates/index.html.erb (124.8ms)

+2

のようにあなたは、HTTPコールを作っています。 '@response ['data']'がnilであるため、Redditでレートリミットやその他のサービスエラーが発生する可能性は非常に高いです。あなたのスクリプトを効率的にするために、 '@response ['data']'と '@response ['data'] ['children']'のhttp応答/存在を確認してください。 – kiddorails

+1

'HTTParty.get(...)'が成功したと盲信してはいけません。それを変数 'response = HTTParty.get(...)'に割り当て、データを処理する前に 'response.success?'か 'response.code'をチェックしてください。 – Stefan

答えて

1

あなたはこのようなエラーが出たとき、あなたがそれを調べることができますので、あなたは常に実際の応答をダンプする必要があります。 ['data']['children']のようなコードを使ってnilのエラーが発生したということは、JSONレスポンスを取得していることを意味しますが、最初のアイテムの1つが欠落していることを意味します(例:['data']は返されません)。

すべてのリクエストが成功したと仮定するだけで、多くのことがHTTPを失敗させる可能性があります。たとえば、がエラーメッセージを教えてくれるエラーメッセージなど、あなたが期待しているものではなく、有効なJSON応答を返す可能性があります。またしても10秒遅れで、あなたはレート制限を打つことが可能

(個人のRedditをテストしたことはありません)が、(「パイソン/ urllibは」のようなrules

多くのデフォルトのユーザーエージェントを読んだり、 " Java ")は、ユニークでわかりやすいユーザーエージェント文字列を奨励するために大幅に制限されています。クライアントクラスを作成

+0

これは問題の子でした​​。要求ごとに異なるユーザーエージェントを使用することで問題は解決しました。 この宝石は非常に役に立ちました。 https://github.com/asconix/user-agent-randomizer 多くのファンに感謝! –

+0

本当にあなたはそれをどうやって尋ねるべきですか?あなたが問題を引き起こした場合、彼らはあなたに対してより劇的な行動を取るかもしれません。 "クライアントのUser-Agent ... **あなたのユーザー名**を連絡先情報として、 ' :<バージョン文字列>(/ u/) 'で変更してください。私はそれがランダムである必要があるとは思わないし、一見すると、彼らはそれが欲しくない。 –

2

httpartyで動作するように非常に良い方法です:

class RedditClient 
    include HTTParty 

    format :json 

    base_uri "http://reddit.com/r/" 

    def self.get_category(category, *opts) 
    opts.reverse_merge(limit: 25) 
    get("/#{category}.json", opts) 
    end 
end 

HTTPartyが私たちのためにJSONの解析を処理し、変換空の応答しようとしませんこの方法です。また、別々にテストする方がはるかに簡単です。

しかしそれでも応答がそれを使用しようとする前に成功したかどうかを確認する必要がありますあなたが .createに単一のハッシュを含む配列を渡す

@response = RedditClient.get_category(category) 
if @response.success? 
    attrs = @response['data']['children'].map do |child| 
    { 
     category: category, 
     link: child['data']['url'], 
     title: child['data']['title'] 
    } 
    end 
    Pic.create!(attrs) 
else 
    # log it or raise some sort of error 
end 

注意。代わりに、ハッシュの配列を渡すことができ、単一のSQL挿入ステートメントにレコードを挿入します。

0

この種のエラーは、ルビーやレールでよく発生します。複数の方法で処理することができます。 @Stefanは次のいずれかを使用することを提案しました。

最も単純にこの

response = HTTParty.get('http://reddit.com/r/#{category}/.json?limit=25') 
if response.success? 
    response_body = response.body 
    # continue 
end 

または

response = HTTParty.get('http://reddit.com/r/#{category}/.json?limit=25') 

case response.code 
    when 200 
    puts "Good!" 
    # Continue your parsing 
    when 404 
    puts "NOT FOUND!" 
    when 500...600 
    puts "ERROR #{response.code}" 
end 

または

begin 
    HTTParty.get('http://reddit.com/r/#{category}/.json?limit=25') 
rescue HTTParty::Error 
    # HTTParty errors like Not found 
rescue StandardError 
    # StandardError like Timeout 
else 
    # continue 
end 
関連する問題