hakeの日記

Windows環境でプログラミングの勉強をしています。

Hpricotでhtmlの解析 その2

Rubyの勉強

SHOUTcastYouTubeのサイトを解析してみる。とりあえずスゴク簡単にできてしまう。ザウルスだとライブラリの読み込みにちょっと時間がかかるかなとは思うものの、後々にメンテナンスなんかを考えるとソースが簡潔になるメリットは大きいと思います。もうひとつBitWarp経由でhtmlソースを取得すると改行が無くなってしまう問題がありましたがHpricotで解析すれば、この問題も気にしなくて済むようになりますね。


<foo class=bar>はfoo.bar、<foo id=bar>はfoo#barという指定方法が可能みたいなので、各タグの中にclass属性が埋め込まれているYouTubeのソースの方が簡単にできた。SHOUTcastの方は(doc/:html/:body/:table)[10]の様にn番目という方法でタグを指定したけど、もっと良い方法がありそうな気がする。
あと、(doc/:html/:body/:table)とした場合に<head>の直下の<table>タグのみ検索対象になるのかと思ったら、もっと内側?にあるタグまで検索対象になってしうことに気がついた、これは注意が必要。


SHOUTcast

#!/usr/bin/env ruby
require "hpricot"
require 'open-uri'
#require "kconv"

doc = Hpricot(open("http://www.shoutcast.com/directory/?genre=House"))
#doc = open("shoutcast.html") { |f| Hpricot(f) }

title = (doc/:html/:head/:title)
#title = (doc/:title)
puts title.text

# 11番目の<table>〜</table>を取得
# 階層に関係なく先頭から11番目に登場する<table>であることに注意
table = (doc/:html/:body/:table)[10]
# その<table>〜</table>の中の
# 最初の<tr>〜</tr>をスキップ、各項目の名称表示であるため為
tr = (table).at("tr").next_sibling
i = 0
# 二番目以降の各<tr>〜</tr>について
while tr
  # <td>が一個のみの<tr>タグをスキップ
  #   <td colspan=…>が存在するか否かで判断
  unless (tr).at("td")["colspan"]
    # <tr>〜</tr>中の各<td>タグ取得
    td = (tr/:td)
    # ジャンル
    p td[4].at("b").inner_text
    # タイトル
    #   <a id="listlinks" …>〜</a>
    p td[4].search("a#listlinks").inner_text
    # plsファイル位置
    p td[2].at("a")["href"]
    i += 1
    break if i == 20
  end
  # 次の<tr>タグ
  tr = tr.next_sibling
end

YouTube

#!/usr/bin/env ruby
require "hpricot"
require 'open-uri'
require "kconv"

SEARCH_WORD = "zaurus"

doc = Hpricot(open("http://www.youtube.com/results?search_query=#{SEARCH_WORD}&search=Search"))
#doc = open("youtube.html") { |f| Hpricot(f) }

title = (doc/:html/:head/:title)
#title = (doc/:title)
puts title.text

# <div class="vtitle" …>なタグを検索
divs = (doc/:html/:body/"div.vtitle")
divs.each do |div|
  a = div.at("a")
  puts a.inner_text.toeuc             # タイトル
  puts a["href"]                      # ファイルID?
  puts div.at("span").inner_text      # 再生時間
end