読者です 読者をやめる 読者になる 読者になる

MA7に応募したはてぶマップについて(詳細編)

技術 ジオ

前回に続いてはてぶマップの話。

今回は内部の作りの説明と作ってみての感想です。
ソースは公開準備中です。

データ作成バッチ (javaで実装)

データ作成の手順は以下の通り。

  • 対象のページ + 対象ワードの抽出(手動。。)

最初ははてぶのホットエントリーとか新着エントリーを全部回せばいいかくらいに思っていたのですが、後に出てくるyahooのローカル検索APIの所で、都道府県コードやジャンルコードを付与してやらないと、一般名詞でもけっこうスポットが引っかかってしまったりで、データがかなりいまいちになってしまったので、ここは手動でやりました。。
はてぶで"東京"、"京都"で検索 -> ページをざっと見て、解析する価値がありそうかを判断 -> 都道府県コードとカテゴリコードを決定 というアナログな手法でページの選定と検索条件を設定しました。
「ページのURL \t 都道府県コード \t ジャンルコード」という形式のCSVを手でポチポチと作成します。
データを増やしていくにあたっては、完全にボトルネックになってしまうので、何か仕組みを検討していきたい所ですが、技術的なハードルはかなり高そうだなと感じてます。(まずは誰でも設定できるような仕組みの提供とか?)

↑が手動なため、そのタイミングで一緒に設定すればいいので、必要は無いっちゃないんですが、将来的に自動化予定!?なので、API経由でブクマ情報を取得しています (& はてなの協賛企業賞も狙っていますww)。

  • 各ページのbodyのテキスト文字列を抽出

ROMEというパッケージを利用しました。
(ファイルが見つからず苦労したので、ここにまとめました。)
次の特徴語抽出APIが文章内での相対的なスコアリングを行っているようだったので、ある程度の長さ毎に一行(=クエリの単位)にして文字列を抽出し、特徴的な単語が見つかりやすくなるようにしました。
今は単純に文字列を抜いてるだけなので、タグ構造を加味する等、ここも色々と改善の余地がある部分です。

元のテキストを形態素解析とかだけして、次のローカルサーチを実行することも可能ですが、速攻でAPIの上限に引っかかりそうな気がしたので、キーフレーズ抽出を挟みました。
(文章の少ないまとめ系のエントリーなどでは、引き当てたいキーワードが浮かび上がってこなかったり、ある1スポットを紹介したエントリーになると、もやはこの仕組みでは太刀打ちがいかなかったので、一部エントリーに関してはここも手動で作業しました。。)

最初にセットした都道府県コードとジャンルコード + ↑で抽出されたキーフレーズで順に検索を実行し、ページの中に登場したと思われるスポットを抽出。地名(ex.新宿)や一般名詞(ex.ラーメン)等が入ってしまうことがあり、そういう時は関係ないスポットが大量に入ってしまうので、該当件数が多い場合は弾いています。

描画と検索で利用するために、GeoHexのコードを付与。詳細は後述。


描画部分

やりたかったこととして、

    • スケールが広くても、画面をピンだらけにしないで操作性を維持するとともに、。
    • 地図全体で表示件数を絞ってしまうと一部エリアに偏る可能性があり、そうなると結局↑も満たさないので、地図全体に万遍なくピンを降らせる。

という2点がありました。
そこで、GeoHexの座標系を用い、各Hex内毎にピンをブクマ数の上位5件までとするという制御を入れることで、↑を実現しました。
現在、最新版はv3ですが、今回の利用方法としては、mapの縮尺とhexのlevel(=大きさ)を対応づけやすいv2のほうが適しているように感じたので、v2のコード体型でデータを保持しています。
結果、渋谷周辺で見てみると、、
f:id:seikoudoku2000:20111107031030p:image:w640
f:id:seikoudoku2000:20111107031031p:image:w640
f:id:seikoudoku2000:20111107031032p:image:w640
f:id:seikoudoku2000:20111107031033p:image:w640

こんな感じになり、無事にやりたかったことを実現できました。
また、ジオ系のデータを扱うスキーマとしては、PostGISや最近ではMongoDB辺りがでてきているような気がしますが、普段使い慣れているものではなく、最初の敷居が高くなってしまいがちですが、GeoHexの座標系を用いると、RDBMSにデータを突っ込み、x座標とy座標の範囲指定という単純なwhere文でデータを引っ張ってこれるというのも、かなり魅力的だなと思ったりしました。

感想

バッチ作成に関しては、"HTMLからスポットに紐づく単語のみを抜き出す"という課題の敷居の高さが思ったよりはるかに高く、全くいけてる仕組みにできませんでした。。(人間のコンテキストを読みとる力ってのはほんとに凄いんだな〜と思ったり。。)
こういう問題に実際にガツンとぶつかったことで、これまで漫然と学習していたテキストマイニング機械学習といった所に対して、目的を持って取り組むことができそうなので、それはそれで良かったはずと自分を励ましつつ、精進を進め、新たな打開策を考えていきたいと思います。
とりあえず、同僚に勧められていながら価格の高さからスルーしていた、↓を購入してみるなどしてみました。

情報検索と言語処理 (言語と計算)

情報検索と言語処理 (言語と計算)


描画部分に関しては作り出す時に頭にあったものにイメージに近い物ができました。(デザインは全くのせられていませんが、、)
ただ、ピンやポリゴンにaddEventListernする所で結構はまり、クロージャ的な話が全く理解できていないことが判明したり、グローバル変数をがんがん使ったりと、コード書きながらちょっと悲しい気分になったので、こちらも勉強し直さねばならないなと痛感したのでありました。まずは蝶々本を読み直す所からかな〜。

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス


最後に、、はてなは今の仕事をするにあたってかなり影響を受けた会社(自分の初期の頃のエントリーにちょこちょこと出てくる)で、中でもはてぶはwebの面白さを教えて続けてくれる大好きなサービスであり、また、GeoHexは初めて見た時から凄いな〜と感じ、端で見ている間にあれよあれよという間にwhere2.0にまで登場してしまう存在に駆け上がり、GeoHexというプロダクトと共に、3年以内にwhere2.0で登壇するという目標をたて、それを果たしてしまった、@sa2daさんの行動力自体にもめちゃめちゃ刺激を受けました。
すんごい微力ですが、このリスペクトする2つのプロダクトを結びつけるというのは、とても楽しい作業で、何ともいえない充実感も感じることができたと同時に、改めて自分の力が及ばない部分を痛感することができたので、これを糧にまた次のステップを考えていきたいな〜と思います。


Mashup Awardという場を提供してくださるとともに、Mashup campの名の下で2度にわたり、電源と無線LAN完備の快適な開発環境+飲み物やらお菓子やらを提供してくださった、リクルート メディアテクノロジーラボの関係各位の皆様には本当に感謝感謝です。(Mashup campなかったら、きっと応募できてませんでした。。)ありがとうございました!!