Fantasy – a Ruby library for scraping Fantasy Premier League

The Fantasy Premier League site has one (quite strange) limitation – the mini league tables aren’t updated live even though the actual team pages are. This makes it a chore to stay updated on how you’re doing compared to your mini league buddies. So I created a small Ruby library to scrape information from the Premier League website and then present it in whichever way is wanted.

The library is available at http://github.com/evenv/fantasy.

It’s released under the MIT license, so feel free to use it for whatever you’d like.

I’ve included the Sinatra app I created along with the library to show updated points for a list of teams. It’s not particularly advanced, but does the trick for me (and works pretty well on the iPhone).

Automatically Unrar Everything In A Folder

This script enters into all subfolders of the given folder, unrars all archives and then deletes the rar files. If the folder name matches HDTV or another filter of your choosing, the script will also move any video files to the root folder and delete the containing folder.

Designed to be run on a regular schedule, the script will skip any folders it has already processed. To run regularly, add to cron.

Here’s the script:

def episode(dir)
  dir.match "HDTV"
end

def unrar_delete(thefile,allfiles)
  if system "/opt/local/bin/unrar e -y %s > /dev/null" % thefile.gsub(' ',' ')
    for file in allfiles
      File.delete(file)
    end
    return true
  end
  return false
end

rootdir = "/Volumes/Filmer/Incoming"

Dir["%s/*" % rootdir].each do |dir|
  if File.directory? dir and not dir.match "UNPACKED"
    ok = false
    Dir.chdir(dir)
    Dir['%s/*.rar' % dir].each do |rarfile|
      puts rarfile
      ok = unrar_delete(rarfile, Dir[rarfile.gsub("part01","part??")]) if rarfile.match "part01.rar"
      ok = unrar_delete(rarfile, Dir[rarfile.gsub(".rar",".r??")]) if not rarfile.match /part[0-9]{2}/
    end

    if ok
      if episode(dir)
        system "mv *.avi %s" % rootdir
        system "mv *.mkv %s" % rootdir
        Dir.chdir(rootdir)
        system "rm -r %s" % dir
      else
        File.rename(dir,"%s UNPACKED" % dir)
      end
    end
  end
end

Export All OmniGraffle Files In A Folder To PDF

So I cooked up this small script that opens all OmniGraffle documents in a folder, and exports them to PDF files. The PDF files are named the same as the Graffle files, and will be saved in the same folder.

To use it, just load up Script Editor, paste, compile, and run. Of course, you could also save it to the AppleScripts folder so you can easily access it.

tell application "Finder"
  set the theFolder to choose folder with
    "Pick a folder containing the OmniGraffle files you want to export to PDF:"
  set theList to every file of the theFolder whose
  name extension is "graffle"
end tell

repeat with theFile in theList
  set theOutFile to ((do shell script "basename \"" & (theFile) & "\"" & " .graffle") & ".pdf")
  set theInFile to theFile as string
  tell application "OmniGraffle Professional 5"
    activate
    open file (theInFile)
    save front window in file theOutFile
    close front window
  end tell
end repeat

Vino v1.3 released

Because of the surprising amount of feedback (and 4000 downloads!) I’ve gotten on my wine organizer program Vino, I decided to spend some hours and fix some of the more glaring issues with the original version of the program. The updated version can be found here.

Here are some of the bigger changes in v1.3:

  • Added fields for added date, quantity and drinking time suggestions.
  • Added library items for pink and bubbly wine.
  • Updated the UI to look a bit more like Cocoa programs should.
  • Wine Library is now a drawer attached to the main window.
  • Added support for custom wine libraries. More about this later on.
  • Added Sparkle support for automatic updates. Thanks to alex for the tip.
  • Added Norwegian localization. Thanks to Jørgen for input on this.
  • Replaced the monster of an icon from the first version with something a little easier on the eyes.
  • Many many tiny fixes hopefully allowing for a more intuitive user experience.
  • I’ve chosen not to release the source code for v1.3. The source for v1.2 is still available. The reasons for this is mainly that some of the code, such as the Sparkle framework support, contain encryption keys. The program is still freeware though, and I have no intentions of changing that fact.

A big thank you to everyone who has contributed with comments, suggestions and linkbacks. Any feedback on this version is appreciated as well.

Vinmonopolet Scraper Code

Okay, so by request here’s the Ruby script I’ve used to scrape vinmonopolet.no for the wines found in Vino.

Caveat: This is not publishing grade code, it is completely hacky and might not work for your setup. It will probably break if vinmonopolet.no updates their page structure even slightly. You will need some coding knowledge to have any use for this. I post it here strictly for educational value, so please bear that in mind.


require 'rubygems'
require 'hpricot'
require 'open-uri'
require 'sqlite3'
require 'iconv'

require 'HTMLEntities.rb'

class String
  def to_iso
    Iconv.conv('ISO-8859-1', 'utf-8', self)
  end
  def fixx
    self.gsub(" "," ").decode_entities.strip
  end
  def camelcase
    self.downcase.capitalize.gsub(/ (.)/) { " #{$1.upcase}" }
  end
end

db = SQLite3::Database.new('vino.db')

wines = {}

base = "http://www.vinmonopolet.no/is-bin/INTERSHOP.enfinity/WFS/store-vmp-Site/no_NO/-/NOK/"
nexturl = ARGV[0]
while nexturl
  puts nexturl
  doc = Hpricot(open([base,nexturl].join))
  doc.search("#productList tr").each do |row|
    next if row.at("th")
    wine = {}
    wine[:polnumber] = row.at("td.id > p").inner_html.match(/(([0-9]+))/)[1]
    wine[:volume] = row.at("td.price em").inner_html.fixx
    if db.get_first_value("SELECT 1 FROM vino WHERE polnumber = '%s' AND volume = '%s';" % [wine[:polnumber],wine[:volume]])
      puts "XX %s" % wine[:polnumber]
      next
    else
      puts "-- %s" % wine[:polnumber]
    end
    wine[:link] = row.at("h3 a").attributes['href']
    wine[:title] = row.at("h3 a").inner_html.fixx
    wdoc = Hpricot(open(wine[:link]))
    wine[:price] = wdoc.at("td.price strong").inner_html.gsub("Kr. ","").fixx
    wdoc.search(".productData li").each do |data|
      wine[:region] = data.at("span").inner_html.fixx if data.at("strong").inner_html.include? "distrikt"
      wine[:varietals] = data.at("span").inner_html.fixx if data.at("strong").inner_html.include? "stoff"
      wine[:winery] = data.at("span").inner_html.fixx if data.at("strong").inner_html.include? "Produsent"
      wine[:type] = data.at("span").inner_html.fixx if data.at("strong").inner_html.include? "Varetype"
    end
    wine[:vintage] = wine[:title].scan(/[0-9]{4}/).last
    db.execute("INSERT INTO vino VALUES (:title,:volume,:price,:region,:varietals,:winery,:polnumber,:type,:vintage,:link);",wine)
  end #wine
  lastlink = doc.at("table.pages tr > td:last a:last")
  begin
    if lastlink.inner_html.include? "Neste"
      nexturl = lastlink.attributes['href']
    else
      nexturl = false
    end
  rescue
    next
  end
end

Usage: Save the file as vinoscan.rb along with HTMLEntities.rb, enter Terminal and go to the folder where it is saved, type

ruby vinoscan.rb "v_PerformSearch-Prod?query=*&nav=true&filter25=Hvitvin&sort=21"

with v_PerformSearch… being the page you want the script to start scraping. (To find this go to vinmonopolet.no and look for matching urls.) The script will follow Next links until it can’t find any more, and save all the wines it comes across into a SQLite database.

It’s important to note that this database is not directly compatible with Vino – I have another script cleaning the data before I copy it into Vino but that script is such a mess I find it hard to believe anyone could have anything to gain from looking at it.

Many thanks to Paul Battley for the HTML Entities library, and even more so to why the lucky stiff for the magnificent hpricot web scraping library.

Introducing Vino

Vino is a small wine organizer program I created to manage wines I’ve tasted and what I thought about them.

It’s pretty basic, but has some nice features such as:

  • Adding wine labels with iSight integration
  • Pre-populated database with 7000 common wines
  • It’s freeware, so if you want it grab it. I can’t promise any further development though.

Get Vino

All thoughts on the program are appreciated.

By the way, if you find the program useful, it’d be great if you registered it at iusethis.com – a great Mac software site.

If anyone is interested, I’d be happy to post the source code both for the program and the tiny Ruby script scraping the wine webshop vinmonopolet.no for wine information.

UPDATE: Source code and scraper code has now been posted.