はてなのブックマーク数順で検索結果を表示する http://www.ark-web.jp/sandbox/wiki/194.html
はてなのブックマーク数順で検索結果を表示する
方法が見当たらなかったので、作りました。
http://okra.ark-web.jp/~konuma/cgi-bin/search.cgi
どうやって使うの? †
- 上記のページに検索フォームがあるので、そこで検索します。
- すると、はてなでブックマークされている数のランキングが表示されます。
- ランキングの対象となるのは、はてなで検索をおこなったときに上位100までに表示されるページのみです。
例えばこんな検索ができます。 †
- rubyについて書いてあるページで、最もブックマークされているのはどこ?
http://okra.ark-web.jp/~konuma/cgi-bin/search.cgi?keyword=ruby - www.ark-web.jpにあるページで、最もブックマークされているのはどこ?
http://okra.ark-web.jp/~konuma/cgi-bin/search.cgi?keyword=site%3Awww.ark-web.jp
追記、これはこっちを使ったほうがいいです。
http://b.hatena.ne.jp/entrylist?sort=count&url=http%3A%2F%2Fwww.ark-web.jp
中身どうなってんの? †
概要 †
- rubyです。
- はてなの検索結果からスクレイピングしています。
http://www.teamerblog.com/wiki/
- 志田さんの作った↓を参考にしています。
YouTube検索結果をスクレイピングして勝手API化- //参考にしているというか、大部分コピーです。。。
詳細 †
- このサービスは以下の三つのファイルから成り立ってます
search.cgi -- 表示部分 Hatena/SearchResultScraper.rb -- 検索およびスクレイピングをする部分 Hatena/page.rb -- 検索結果の1ページあたりのデータを保持する部分
そんなに長いコードではないので、全部掲載します。 - search.cgi
#!/usr/bin/ruby require 'cgi' require 'Hatena/SearchResultScraper' require 'Hatena/page' require 'kconv' #はてなでの検索結果を取得する。 def scrape keyword scraper = Hatena::SearchResultScraper.new(Kconv.toutf8(keyword), 10) scraper.open pages = scraper.order_by_bookmark_count end #検索結果を表示する def print_pages pages pages.each do |page| print "<a href="#{page.url}">#{page.title}</a> <strong><a href="http://b.hatena.ne.jp/entry/#{page.url}">#{page.bookmark_count}</a></strong><br>" end end print "Content-type: text/html\n\n" cgi = CGI.new keyword = cgi['keyword'] print <<EOS <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=EUC_JP"> <title>form</title> </head> <body> <form action="./search.cgi" method="get" charset=UTF-8"> <input name="keyword" value="#{keyword}"> <input type="submit" value="Search"> </form> EOS print_pages(scrape(keyword)) unless keyword.empty? print <<EOS </body> </html> EOS
- Hatena/SearchResultScraper.rb
require 'open-uri' require 'cgi' require 'rubygems' require 'hpricot' require 'Hatena/page' module Hatena class SearchResultScraper @@search_base_url = "http://search.hatena.ne.jp/search?ie=utf8&word=" def initialize keyword, count = 10 @keyword = keyword @count = count end #URLを開き、検索をおこなう。@countで指定された回数だけ検索結果を読み込む def open @pages = [] @count.times do |i| page = open_page(i+1) break if page.size == 0 @pages.concat(page) end @pages end #ブックマーク件数でソートする。 def order_by_bookmark_count @pages.sort! @pages.reverse! end private #page番目の検索結果をスクレイピングする def open_page page url = @@search_base_url + CGI.escape(@keyword) + "&page=" + CGI.escape(page.to_s) html = Kernel.open(url).read replace_document_write_javascript(html) scrape(Hpricot.parse(html)) end #検索結果のページをスクレイピングする def scrape result pages = [] result.search("div.hatena-search-result-item").each do |page_html| page = Hatena::Page.new page.title = scrape_title(page_html) page.url = scrape_url(page_html) page.bookmark_count = scrape_bookmark_count(page_html) pages << page end pages end #邪魔なjavascriptの文字列を置換する def replace_document_write_javascript html html.gsub!(%r{<script language="javascript" type="text/javascript">.*?document.write\('(.*?)'\).*?</script>}m, '\1') end #タイトルをスクレイピングする def scrape_title page_html page_html.search("//h3//a").inner_html end #URLをスクレイピングする def scrape_url page_html page_html.search("//h3").inner_html.sub(/<a href="([^"]+)">.+/, '\1') end #ブックマーク件数をスクレイピングする def scrape_bookmark_count page_html page_html.search("//span[@class='users']").inner_html.sub(/(<.+>)?<a.*?>(\d+) users?<\/a>(<\/.+>)?/, '\2') end end end
- Hatena/page.rb
module Hatena class Page attr_accessor :url attr_accessor :title attr_accessor :bookmark_count #ブックマーク件数で比較する(ブックマーク件数でソートするときのために) def <=> another self.bookmark_count.to_i <=> another.bookmark_count.to_i end end end
制限事項 †
- 日本語で検索できません。
いずれ対応する予定です。対応しました。
- 遅いです。
- はてなの検索画面を10ページ分もスクレイピングしているので。。。
- ランキングは正確じゃないかも
- ランキングの対象となるのが「はてなの検索結果の上位100まで」なので、それより下の順位にあるページが無視されています。
コメント †
- ブックマーク数のところをリンクにして、はてなブックマークページ(って言うのかな?)へ飛ぶようにしました。 -- 小沼 2007-01-30 (火) 12:14:39