Skip to content

Instantly share code, notes, and snippets.

@pca2
Created October 17, 2018 00:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pca2/7ed695aa9e6a0e1ca7c125cde8b0a5f8 to your computer and use it in GitHub Desktop.
Save pca2/7ed695aa9e6a0e1ca7c125cde8b0a5f8 to your computer and use it in GitHub Desktop.
BitBar Plugin that Scrapes election odds from FiveThirtyEight's Midterm election tracker
#!/usr/bin/env ruby
# <bitbar.title>538 Midterm Tracker</bitbar.title>
# <bitbar.version>v1.0</bitbar.version>
# <bitbar.author>Carleton Atwater</bitbar.author>
# <bitbar.author.github>pca2</bitbar.author.github>
# <bitbar.desc>Scrapes election odds from FiveThirtyEight's Midterm election tracker</bitbar.desc>
# <bitbar.image>https://imgur.com/bCF8fyg.png</bitbar.image>
# <bitbar.dependencies>ruby,Chrome, Mac OS X</bitbar.dependencies>
# This code is pretty hacky, but it was a fun 1 hour project to track something 20ish days away.
require 'nokogiri'
require 'open-uri'
feed = Nokogiri::XML(open("https://fivethirtyeight.com/tag/2018-election/feed/"))
#Because forecast page requires JS to load the numbers, Nokogiri can't parse the page on its own.
#Headless Chome seems like the simplest way to grab the properly rendered page
house = `/Applications/'Google Chrome.app'/Contents/MacOS/'Google Chrome' --headless --disable-logging --dump-dom 'https://projects.fivethirtyeight.com/2018-midterm-election-forecast/house/' 2>/dev/null`
parsed_house = Nokogiri::HTML(house)
dem_house = parsed_house.css('p .dem-p').text
rep_house = parsed_house.css('p .rep-p').text
house_update = parsed_house.css('.cardset-timestamp').text.strip
senate = `/Applications/'Google Chrome.app'/Contents/MacOS/'Google Chrome' --headless --disable-logging --dump-dom 'https://projects.fivethirtyeight.com/2018-midterm-election-forecast/senate/' 2>/dev/null`
parsed_senate = Nokogiri::HTML(senate)
dem_senate = parsed_senate.css('p .dem-p').text
rep_senate = parsed_senate.css('p .rep-p').text
#Output
puts dem_house #menue bar level
#Revealed on click
puts "---"
puts "House:"
puts "Dem: #{dem_house}"
puts "GOP: #{rep_house}"
puts "---"
puts "Senate:"
puts "Dem: #{dem_senate}"
puts "GOP: #{rep_senate}"
puts "---"
puts house_update
puts "---"
puts "🦊 FiveThirtyEight Election Forecast | href=https://projects.fivethirtyeight.com/2018-midterm-election-forecast/house/"
feed.css("item")[0..2].each do |item|
date = Date::parse(item.css('pubDate').text)
puts "#{date.strftime("%Y-%m-%d")}: #{item.css('title').text} | href=#{item.css('link').text}"
end
puts "---"
puts "Refresh... | refresh=true"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment