Yahoo!デベロッパーネットワークのキーフレーズ抽出で遊んでみる

キーフレーズ抽出
http://developer.yahoo.co.jp/webapi/jlp/keyphrase/v1/extract.html
を試すのに何か面白いデータは無いかと考えていたが、2chのスレのデータでも投げてみる。板のスレタイ投げてる人は結構いるみたいだしね。

普段使いがnavi2chなので、そこから本文のデータだけ投げるコード

(defun my-navi2ch-article-keyphrase ()
  (interactive)
  (let (sentence str)
    (dolist (msg navi2ch-article-message-list)
      (when (listp (cdr msg))
	(setq str (cdr (assq 'data (cdr msg))))
	;;Beアイコン削除
	(when (string-match "^sssp://img\.2ch\.net/ico/.*\.gif" str)
	    (setq str (replace-match "" nil nil str)))
	(setq sentence (concat sentence (concat str "\n")))))
    (my-navi2ch-article-keyphrase-send-request sentence)))

;;自分のappidを入れる
(defvar my-navi2ch-article-keyphrase-appid "")

(defun my-navi2ch-article-keyphrase-send-request (sentence)
  (let ((post-str  (navi2ch-net-get-param-string 
			    (list 
			     (cons "appid" my-navi2ch-article-keyphrase-appid)
			     (cons "sentence" sentence))
			    'utf-8)))
    (message "sentence-width %s" (length post-str))
    ;;POST出来るデータは100kとの仕様なので切り詰め
    (when (> (length post-str) 100000)
      (setq post-str (substring post-str 0 100000))
      ;;エンコード済みの%ddの境界をきちんとしないとエラーが返る
      (while (not (string= "%" (substring post-str -1 nil)))
	(message "%s" (substring post-str -1 nil))
	(setq post-str (substring post-str 0 -1)))
      (setq post-str (substring post-str 0 -1)))
      (message "chopped sentence-width %s" (length post-str))
    (let* (word
	  (proc (navi2ch-net-send-request
		 "http://jlp.yahooapis.jp/KeyphraseService/V1/extract?"
		 "POST"
		 (list
		  (cons "User-Agent" navi2ch-net-user-agent)
		  (cons "Content-Type" "application/x-www-form-urlencoded"))
		 post-str))
	  (cont (decode-coding-string (navi2ch-net-get-content proc) 'utf-8)))
      (with-temp-buffer
	(insert cont)
	(goto-char (point-min))
	(save-excursion
	  (when (search-forward "<Error>" nil t)
	    (re-search-forward "<Message>\\(.*\\)</Message>" nil t)
	    (error "ERROR: %s" (match-string 1))))
	(goto-char (point-min))
	(save-excursion
	  (while (re-search-forward "<Keyphrase>\\(.*\\)</Keyphrase>" nil t)
	    (setq word  (match-string 1))
	    (re-search-forward "<Score>\\(.*\\)</Score>" nil t)
	    (message "%s : %s" word (match-string 1))))))))

表示されている"range"の分だけ取得することに注意。
で、こんなスレ
はてなダイアリー part 34
http://pc11.2ch.net/test/read.cgi/blog/1228449796/
を開いた状態で、M-x my-navi2ch-article-keyphrase してやると、以下のようにMessageで表示されます。右はスコア。

d.hatena.ne.jp : 100
f.hatena.ne.jp : 94
read.cgi : 88
massa-will : 83
pc11.2ch.net : 83
hatenadiary.g.hatena.ne.jp : 69
hatena.g.hatena.ne.jp : 65
www.hatena.ne.jp : 60
beyond.2log.net : 58
i.hatena.ne.jp : 57
アンテナ : 56
はてなダイアリー : 56
deathtrapcall : 56
web2.0 : 41
メンテナンス : 38
counter.hanena.ne.jp : 38
フォトライフ : 36
anond.hatelabo.jp : 36
ユーザー : 35
ja.wikipedia.org : 35

こうして見ると、やはりYahooという検索企業のツールだけあって、urlのスコアが高くなっているようです。社内で実際に使われてるコードっぽい雰囲気です。
このスレでは顕著ではないが、画像系のスレだとurlのファイル名の部分も「注目」しているのが分かります。
前処理としてurlのデータは削っておいた方がいいかも。

基本的には形態素解析の名詞重視+url重視くらいの感じっぽいので、データ解析的に使うのなら(「きのこvsたけのこ」とか投票のランキングとか)、形態素解析して単語の出現頻度数えた方がいいかもしれない。

何にせよ、こういう面白いツールを提供してくれるYahoo!には今後も期待していきたいです。