Skip to content

Instantly share code, notes, and snippets.

@Ethan826
Created November 4, 2016 18:41
Show Gist options
  • Save Ethan826/8662da6dc6bf48dd48694fd2249b68bf to your computer and use it in GitHub Desktop.
Save Ethan826/8662da6dc6bf48dd48694fd2249b68bf to your computer and use it in GitHub Desktop.
Scrape poll aggregators for current odds
#!/usr/bin/env ruby
require 'nokogiri'
require 'open-uri'
module OddsGetter
class OddsGetter
def initialize(url:, selector:, selector_type: :xpath, processing_func: ->(h) { h.text.to_f })
@url = url
@processing_func = processing_func
@selector = selector
@selector_type = selector_type
end
def odds
processing_func.call(odds_string)
end
private
attr_reader :url, :processing_func, :selector, :selector_type, :html
def html
@html ||= Nokogiri::HTML(open(url))
end
def odds_string
selector_func = { css: :at_css, xpath: :at_xpath }.fetch(selector_type)
html.public_send(selector_func, selector)
end
end
site_data = {
'538 Odds' => { url: 'http://projects.fivethirtyeight.com/2016-election-forecast/', selector: 'div.candidate.one.dem p.candidate-val.winprob', selector_type: :css },
'Betting Market Odds' => { url: 'https://electionbettingodds.com/', selector: '//table//span[text()="Presidency"]/ancestor::table//img[@src="/Clinton.jpg"]/ancestor::tr//p[1]' },
'Princeton Odds' => { url: 'http://election.princeton.edu/electoral-college-map/', selector: '//li[contains(text(), "Clinton Nov.")]', processing_func: -> (h) { h.text.match(/random drift.*?(\d+(\.\d)?)/)[1].to_f } }
}
puts "2016 Election Odds\n=================="
padding = site_data.keys.map { |k| site_data.keys.map(&:length).max - k.length }
site_data.each_with_index do |(site, site_data), i|
puts "#{site}:#{' ' * padding[i]} #{OddsGetter.new(site_data).odds}"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment