Il y a un peu plus d’un mois, Starcraft 2 est sorti. Ayant été un fan modéré du premier, j’ai pris beaucoup de plaisir à jouer au second, notamment en ligne dans le système de leagues. Et pour suivre mon classement dans les différentes leagues, je me suis amusé à développer quelques scripts en PHP pour télécharger les données à partir du site de Blizzard, les stocker dans mongodb et les visualiser. Etant donné que Blizzard ne propose pas d’API, il a fallu récupérer les pages HTML brutes et les parser avec simplehtmldom. Ces scripts sont mal codés, mais disponibles sur mon compte github.

J’ai décidé de recommencer from scratch cette application, mais en partant vers un langage et des technos que je ne maitrise pas particulièrement, à savoir Ruby puis peut-être plus tard Ruby on Rails.

Cet article décrit comment j’ai très basiquement téléchargé une page simple web et ayant récupéré dans la structure de celle ci quelques informations. Pour cela, j’ai du utiliser les modules Curb (bindings ruby de curl) et Nokogiri (parseur html, xml, sax…):

$ gem install curb
$ gem install nikogiri

On commence par écrire une petite fonction pour télécharger une page:

def http_request(url)
  curl_handler = Curl::Easy.new()
  curl_handler.url = url
  curl_handler.http_get

  return curl_handler.body_str
end

Puis une autre, pour parser la page téléchargée. Nous faisons une utilisation intensive de xpath pour trouver les éléments désirés:

def html_profile_parse(url)
    profile = Hash[]

    profile['link'] = url

    html_contents = http_request(url)

    html_doc = Nokogiri::HTML(html_contents)

    profile_header = html_doc.xpath('//div[@id="profile-header"]')

    profile_header_nick = profile_header.xpath('//h2/a/text()')
    if profile_header_nick.count
        profile_nick = profile_header_nick[0].content
        profile['nick'] = profile_nick
    end

    profile_header_nick_span = profile_header.xpath('//h2/a/span')
    if profile_header_nick_span.count
        profile_id = profile_header_nick_span[0].content
        profile['id'] = profile_id
    end

    profile_header_hf_points_h3 = profile_header.xpath('//h3')
    if profile_header_hf_points_h3.count
        profile_hf = profile_header_hf_points_h3[0].content
        profile['hf'] = profile_hf
    end

    return profile
end

Une fois ce code structuré, cela donne:

#!/usr/bin/env ruby

require 'curb'
require 'nokogiri'

def http_request(url)
    ...
end

def html_profile_parse(url)
    ...
end

url = 'http://eu.battle.net/sc2/fr/profile/491479/1/myc/'
profile = html_profile_parse(url)

print profile

Et dans le shell:

$ chmod a+x fetch.rb
$ ./fetch.rb
{"link"=>"http://eu.battle.net/sc2/fr/profile/491479/1/myc/", "nick"=>"myc", "id"=>"#456", "hf"=>"2950"}