Возникли проблемы с файлом Ruby от Dashing

У меня возникли проблемы с twitter_user.rb, который предполагается получить количество твитов, подписчиков и подписок для данного имени пользователя в Твиттере.

Я предполагаю, что я должен заменить TWITTER_USERNAME в строке 9 на имя пользователя Twitter, которое меня интересует. Я сделал это и начал лихо, но я получил:

scheduler caught exception:
undefined method '[]' for nil:NilClass
/.../jobs/twitter_user.rb:19:in 'block in <top (required)>'

Похоже, проблема связана со строкой 19, а именно:

tweets = /profile["']>[\n\t\s]*<strong>([\d.,]+)/.match(response.body)[1].delete('.,').to_i

Может ли кто-нибудь сказать мне, что происходит и как это исправить?


person user1893354    schedule 11.11.2013    source источник
comment
Проблема в том, что код не был написан умным образом. Использование регулярных выражений для синтаксического анализа XML или HTML — это ожидание крушения, если только его содержимое НЕ ПРИНАДЛЕЖИТ человеку, пишущему код, и это содержимое не изменится, и это тривиальная задача. Измените один из этих трех, и вероятность взлома кода быстро возрастет. Нам нужно увидеть образец HTML, с которым вы столкнулись, чтобы мы могли воспроизвести проблему. Вопросы, касающиеся проблем с написанным вами кодом, должны описывать конкретную проблему — и включать допустимый код для ее воспроизведения — в самом вопросе. См. инструкции на SSCCE.org.   -  person the Tin Man    schedule 11.11.2013
comment
Я думаю, вы правы. Даже не похоже, что задание выполняется в веб-приложении, которое они сделали foobugs-dashboard.herokuapp.com/ телевизор   -  person user1893354    schedule 11.11.2013


Ответы (4)


Ваше предположение неверно. Программа ищет переменную среды с именем TWITTER_USERNAME, для которой задано соответствующее имя пользователя. Если эта переменная не существует, код использует вместо нее foobugs.

Если вы предпочитаете изменять код, а не устанавливать переменную среды, измените

twitter_username = ENV['TWITTER_USERNAME'] || 'foobugs'

to

twitter_username = 'myusername'
person Borodin    schedule 11.11.2013

Это непроверенный код, но это общая идея того, как он должен быть написан. Если вы клонируете исходный код на исходной странице, вы можете настроить его для своих целей (т.е. исправить):

require 'nokogiri'

doc = Nokogiri::XML(content)

tweets = doc.at('profile strong').text.delete('.,').to_i
following = doc.at('following strong').text.delete('.,').to_i
followers = doc.at('followers strong').text.delete('.,').to_i

Вышеупомянутые три строки можно сократить до чего-то вроде:

tweets, following, followers = %w[profile following followers].map{ |tag|
  doc.at("#{ tag } strong").text.delete(',.').to_i
}

Опять же, без пригодного образца XML/HTML я не могу сделать намного больше, но на практике мы (программисты) не должны использовать регулярные выражения для анализа XML или HTML. Очень легко сломать шаблон с любым из этих типов файлов.

person the Tin Man    schedule 11.11.2013

Мне удалось решить ту же проблему для себя, используя вместо этого API Twitter для извлечения соответствующей информации. Похоже, веб-страница слишком сильно изменилась, чтобы парсинг работал, и она также может перестать работать снова без предупреждения, как уже говорили разные люди...

Это решение, которое я использовал.

#### Get your twitter keys & secrets:
#### https://dev.twitter.com/docs/auth/tokens-devtwittercom
Twitter.configure do |config|
  config.consumer_key = 'YOUR_CONSUMER_KEY'
  config.consumer_secret = 'YOUR_CONSUMER_SECRET'
  config.oauth_token = 'YOUR_OAUTH_TOKEN'
  config.oauth_token_secret = 'YOUR_OAUTH_SECRET'

end

twitter_username = 'foobugs'

MAX_USER_ATTEMPTS = 10
user_attempts = 0

SCHEDULER.every '10m', :first_in => 0 do |job|
  begin
    tw_user = Twitter.user("#{twitter_username}")
    if tw_user
        tweets = tw_user.statuses_count
        followers = tw_user.followers_count
        following = tw_user.friends_count

        send_event('twitter_user_tweets', current: tweets)
        send_event('twitter_user_followers', current: followers)
        send_event('twitter_user_following', current: following)

    end
  rescue Twitter::Error => e
    user_attempts = user_attempts +1
    puts "Twitter error #{e}"
    puts "\e[33mFor the twitter_user widget to work, you need to put in your twitter API keys in the jobs/twitter_user.rb file.\e[0m"
    sleep 5
    retry if(user_attempts < MAX_USER_ATTEMPTS)
  end
end
person user2991510    schedule 15.11.2013

Я решил, заменив эту строку:

followers = /<strong>([\d.]+)<\/strong> Follower/.match(response.body)[0].delete('.,').to_i

с этими двумя:

followers_count_metadata = /followers_count&quot;:[\d]+/.match(response.body)
followers = /[\d]+/.match(followers_count_metadata.to_s).to_s
person Diego D    schedule 03.03.2014