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 nikogiri
On commence par écrire une petite fonction pour télécharger une page:
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:
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:
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:
$ ./fetch.rb
{"link"=>"http://eu.battle.net/sc2/fr/profile/491479/1/myc/", "nick"=>"myc", "id"=>"#456", "hf"=>"2950"}