hashtagsjpをスクレイピングしてはてダ用に変換するスクリプト
概要
Google Chrome 5.0 betaを騙って、hashtagsjpからつぶやきを取ってきて1行1tweetに変換します。
XPathを使ってるのでとっても見通しが良い実装だと自画自賛w
はてダに直接張れるHTMLを標準出力に吐き出しますが、cssは出力結果に合わせていぢって下さい。
ソースを晒しておく
#!/usr/bin/ruby require 'net/http' require 'rexml/document' include REXML class HashtagsJP attr_reader :timelines HTTP_HEADERS = { 'User-Agent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.9 Safari/533.2', 'Accept' => 'application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5', 'Accept-Charset' => 'Shift_JIS,utf-8;q=0.7,*;q=0.3', 'Accept-Language' => 'ja,en-US;q=0.8,en;q=0.6', } HOST = "hashtagsjp.appspot.com" URI_ROOT = "http://" + HOST DIR = "/tweets/" XPATH_EXPR = '//html/' + 'body/' + 'div[@id="wrap"]/' + 'div[@id="main"]/' + 'div[@id="main_l"]/' + 'div[@class="box_body"]/' + 'div[@class="tl clearfix"]' def initialize(tag) @server = Net::HTTP.new(HOST, 80) @tag_path = DIR + tag @timelines = [] end def parse(html) html.delete!("\r\n\t") html.gsub!(%r|<script.+?</script>|m, "") html.gsub!(%r|<OBJECT.+?</OBJECT>|m, "") html.gsub!('<a href="/', '<a href="' + URI_ROOT + "/") html.gsub!(" ", " ") html.gsub!("&", "&") doc = Document.new html count = @timelines.count XPath.each(doc, XPATH_EXPR) do |element| tl = element.to_s tl.gsub!('</a></strong>', '</a></strong> ') tl.gsub!(%r|> +<|, "><") @timelines.push tl end tweets = @timelines.count - count STDERR.puts "parsed " + tweets.to_s + " tweet(s)." end def fetch(page) path = @tag_path.dup path << "/" + page.to_s if page != 1 html = self.get(path) self.parse(html) end def fetch_all(pages) 1.upto(pages) do |page| self.fetch(page) end end def get(path) req = Net::HTTP::Get.new(path) HTTP_HEADERS.each do |key, value| req[key] = value end STDERR.print "fetching: " + URI_ROOT + path + " ..." res = @server.request(req) STDERR.puts " done." res.body end end paegs = 1 begin raise "arguments error" if ARGV.count != 1 && ARGV.count != 2 tagname = ARGV[0] pages = ARGV[1].to_i if ARGV.count == 2 rescue STDERR.puts "usage: " + $0 + " hashtag [pages]" exit 1 end hashtag = HashtagsJP.new(tagname) hashtag .fetch_all(pages) timelines = hashtag.timelines while timelines.count > 0 do tl = timelines.pop.to_s puts tl end
使い方
例えば、#flosssのハッシュタグを2ページ分抜き出すには、下記のように実行します。
shingo@shingo-server:~$ ./tweet-format.rb flosss 2 > flosss.txt fetching: http://hashtagsjp.appspot.com/tweets/flosss ... done. parsed 20 tweet(s). fetching: http://hashtagsjp.appspot.com/tweets/flosss/2 ... done. parsed 9 tweet(s). shingo@shingo-server:~$
これからの勉強会は
事前のhashtagsjpへの公式ハッシュタグの登録と、帰宅してからのまとめエントリをお忘れなくw*1
以前C#でスクレイピングやりましたが
前のサイトと比べて綺麗なXHTMLだったので、Tidyのお世話にならなくて良かったです。というか脊髄反射的にTidyを通したらハマったというのはここだけのヒミツw
*1:先週金曜日の分を纏めようとしたら、もう無かった。orz