Googleモバイルのテストツールを使って広告を取ってくるrubyスクリプト

Hpricotの練習に作成しました。Googleモバイル広告のテストツールをこちらで公開しています。これを使って、検索結果に表示される広告をとってきます。

#!/usr/local/env/ruby -Ku
require 'uri'
require 'rubygems'
require 'hpricot'
require 'nkf'
require 'open-uri'

BASE_URL = "http://www.google.com"

def doc(url)
  Hpricot(open(url, {'Accept' => 'text/html, application/xhtml+xml, application/xml'}).read)
end

def search_with(q, carrier = "jp-ntt")
  URI.encode(<<-URI.gsub(/\s+/,''))
    #{BASE_URL}/m/search?
    adtest=on&
    mrestrict=xhtml&
    adtestcarrier=#{carrier}&
    hl=ja&adtestmarkup=xhtml&
    site=search&
    q=#{NKF.nkf("-w", q)}
  URI
end

def advertises(doc)
  ad_text =  (doc/"div[@id = 'ad.top']").text
  ad_text.empty? ? [] : ad_text.gsub(/\?/,' ').split(/\[AD\]\s/)[1..-1]
end

def next_link(doc)
  (doc/:a).each do |e|
    return BASE_URL + e.attributes['href'] if e.inner_text == '次へ'
  end 

  nil
end

def carrier_code_of(carrier)
  converter = {'i' => 'jp-ntt',
               'e' => 'jp-kddi',
               's' => 'jp-sb'}

  converter[carrier]
end

def main
  link = search_with(ARGV[0], carrier_code_of(ARGV[1] || 'i'))
  rank = 1
  
  (1..10).each do |i|
    doc = doc(link)
    ads = advertises(doc)
    result = (ads.empty? ? 
              "広告はありません" : 
              "[#{rank}]" + ads.join("\n[#{rank + 1}]"))
    
    puts /win32/ =~ RUBY_PLATFORM ? NKF.nkf("-W -s", result) : result 
    break unless ((link = next_link(doc)) && !ads.empty?)
    sleep(1)
    rank += ads.size
  end
end

main
使い方と結果

$ ruby parse_ads.rb 着うた
[1]最新着うた、大量配信中 - アーティスト公式サウンド - artistofficial.com
[2]ポケメロ JOYSOUND - 最新メロうた好評配信中! - poke.jp/pokemelo
[3]ジャオジャオ(無料) - ヒマつぶしはココで! - jao2.jp/
[4]着うた無料ダウンロード - 最新曲も取り放題! - recochaku.com
[5]高音質の無料着うた - 最新高音質の着うたが無料 - utax.mobi
[6]アニマックス - アニソン原盤着うた(R) - am.spe.jp
[7]完全無料ミュージックゼロ - 高音質な最新曲を無料でDL - musiczero.jp
[8]セガカラmelody - 着うたムービーあります - www.yoc345.com/del/
[9]セガカラMelody - 大人気コンテンツが満載 - wawa77.xsrv.jp/7/
[10]無料ゲーム小説デコメ - ゲーム小説画像投稿はここ - k.just.st/qr/2489
[11]最新J-popもUSENで - 資料請求はコチラから - www.usen-cs.com
[12]着うた検索はココから - 厳選人気着うたサイト - ad-lpo.jp/chaku_uta/
[13]18日で16.8kg痩せた秘密。 - その秘密を初公開します。 - www.up-health.com
[14]高校生でも稼げた - 携帯のみで3日で58万! - mobile.incomes.jp/
[15]名前や生年月日等で占う - 当たる占いを紹介中 - www.tdmdra.com
[16]今だけ無料-高確率懸賞 - 豪華賞品!現金もGETッ - mt.spk.tc/
[17]いろいろな着うたリンク集 - 無料GETできるサイト有り - katy.jp/yntwakao
[18]無料で稼ぐには - 毎月のお小遣いを稼ぐ - one-prime.com/k2/top
[19]最新着うた、大量配信中 - アーティスト公式サウンド - artistofficial.com
[20]ポケメロ JOYSOUND - 最新メロうた好評配信中! - poke.jp/pokemelo

補足

require 'rubygems'

「win32版ruby」はこれがなくても動くが、少なくとも「universal-darwin9.0版ruby」はこれがないと、Hpricotが使えない。

def doc(url)
  Hpricot(open(url, {'Accept' => 'text/html, application/xhtml+xml, application/xml'}).read)
end

Acceptヘッダをきちんと指定しないと、openしてとってくる際に、HTML形式で返されて解析しにくいのでここで指定している。

def advertises(doc)
  ad_text =  (doc/"div[@id = 'ad.top']").text
  ad_text.empty? ? [] : ad_text.gsub(/\?/,' ').split(/\[AD\]\s/)[1..-1]
end

「doc/"div[@id = 'ad.top']"」はCSSセレクタの形式でとってくるdivを指定している。「@id = 'ad.top'」より、id属性の値が「ad.top」のdiv要素をとってくることができる。
「gsub.(/\?, ' '/)」は、HTML上の「&nbsp;」がtextメソッドによって「?」になってしまうので、それを空白に置換。
「plit(/\[AD\]\s/)[1..-1]」は、解析結果が「[AD] 1つめの広告[AD] 2つ目の広告」のような形式になるので、「[AD] 」でsplitし、すると、配列の先頭要素は「""」になるので、2つ目の要素からとってくる。
また、docにid要素がad.topのdivがない場合、ad_textの結果が「""」になり、[1..-1]によって結果がnilになってしまうので、その場合は空の配列を返すようにした。advertisesメソッドは配列を返すというようにしたいため。

break unless ((link = next_link(doc)) && !ads.empty?)

これは、「次へ」のリンクがない(検索がそこで終了)か、広告表示がなくなったら終了する。

参考

うーん。advertisesメソッドもっと綺麗にならないかな。Hpricotもう少し読まないといけないな。「&nbsp;」の問題とか、絶対回避できそう。