プログラムから自動でGoogle検索して、結果を収集したい時がたまにある。
今回は、Google App Engine と、Google Custom Search APIを使って、Google検索を自動化する方法をメモ。サンプルでは、価格.comのレビューのみを取得するフォームを作ってみた。
Google Custom Search API は、Google Custom Search サービスを外部から操作できるAPI。100リクエスト/日まで無料だ。それ以上リクエストしたい場合は、1000リクエスト毎に5ドル支払えば検索可能となる。1日100件ぐらいであれば、Google Appe Engine側も無料範囲で十分まかなえる量だ。
Custom Search APIを有効にする
まずは、Custom Search APIが使えるように、有効化とAPIキーを取得する。
Google Developers Console にログインして、該当のプロジェクトを選択し、「APIと認証」から「API」メニューを選択する。
APIの一覧からCustom Search APIを探し、右のボタンを押す。
ちなみに、100リクエスト/日以上検索したい場合は、API名を選択後に表示される画面で割り当てを選択し・・・
ここのSet billable limitsから、1日のリクエスト可能数を引き上げる事ができる。(※プロジェクトの課金を有効にしておく必要がある。)
続いてAPIにアクセスするためのキーを取得する。「APIと認証」から「認証情報」を選択する。
次に表示される画面で、「新しいキーを作成」から「サーバーキー」を選択する。OAuthは、例えばユーザー情報を取得するようなAPIを使用する時に選択する。今回は検索のみを使用するので、サーバーキーでOKだ。
許可IPアドレスの設定は今回空欄とした。特定のIPアドレスのサーバーからのみキーを有効としたい場合は設定する。
これでキーが作成できた。このキーはプログラムからAPIへ接続する際に使用する。
Google Custom Searchを作成する
APIキーを取得したら次は Google Custom Search で検索エンジンを作成する。Custom Search APIはここで作成した検索エンジンを操作するAPIだ。
Google Custom Search へアクセスし、新しい検索エンジンを作る。
検索対象のサイトドメインを登録する。かならず1つのドメインを指定する必要がある。今回はとりあえず kakaku.com(あとで変更する) を入力し、検索エンジンの名前を指定。
これで検索エンジンが完成。コントロールパネルへアクセスする。
ここから検索エンジンのIDを取得しておく、IDもAPIキー同様にプログラムからAPIへアクセスする場合に必要。
今回は、価格.comのレビューのみを取得する事が目的なので、その他のページがヒットしないよう、レビューページのURLのみをターゲットにする。対象サイトを選択して・・・
レビューページのURLを入力する。商品IDなど動的に変わる部分は*
でワイルドカード指定ができる。
これで、価格.comのレビューページだけがヒットする検索エンジンが完成した。あとはこいつをプログラムから呼び出す処理を実装する。
検索処理を実装する
まずはキーワードを入力するフォーム。
<form role="form" method="post" action="search">
<div class="form-group">
<label for="keyword">検索キーワード</label>
<input type="text" id="keyword" name="keyword">
</div>
<button type="submit" class="btn btn-default">検索</button>
</form>
次にリクエストハンドラ。キーワードを取得して、しかるべきパラメータでAPIのURLへ送信。戻り値はJSON。※APIの詳細は、Google公式ドキュメントを参照。
import json
import logging
import urllib
from google.appengine.api import urlfetch
from lib.controller import *
class Top(Controller):
def get(self):
self.draw_template('front/cse/top.html')
class Search(Controller):
def post(self):
# キーワードを得る(URLエンコードしておく)
keyword = self.request.get('keyword')
keyword = urllib.quote(keyword.encode('utf-8'))
# リクエストパラメータ組み立て
url = 'https://www.googleapis.com/customsearch/v1'
url += '?key=%s' % '生成したAPIキー'
url += '&cx=%s' % '作成した検索エンジンID'
url += '&q=%s' % keyword
# 検索
result = urlfetch.fetch(url)
logging.info(url)
items = list()
if not 200 <= result.status_code <= 299:
# エラー
logging.error('google custom search error: $s' % str(result.status_code))
logging.error(result.content)
else:
# 結果を得る
content_dict = json.loads(result.content)
items = content_dict.get('items', list())
self.set_template_value('items', items)
self.draw_template('front/cse/search.html')
url_map = [
('/cse/top', Top),
('/cse/search', Search),
]
application = webapp.WSGIApplication(url_map, debug=True)
items
に検索結果のリストが格納される。
Googleは、商品情報や、レビュー、レシピなど、特定の情報については、ルールに従ってHTML(構造化データ)を組んでおけば、意味のある情報としてインデックスしてくれる。たとえば、レビューのタイトルや評価の星の数などだ。
価格.comやヨドバシなどそれなりのショッピングサイトは、この構造化データに準じてサイト構築してくれており、これらのサイトに対して検索した Custom Search API の戻り値も構造化されていて参照しやすい。
つまり、戻されたJSONデータの中には、レビューのタイトル、本文(一部)、評価数(星の数)が、(ほぼ)おなじキー名で格納されているので取り出しやすいのだ。
ちょっと話は脱線したけど、ここまでできれば後はcronで自動化したりと自由自在だ。
実はこの構造化データの値も条件としてフィルタリングできるので、「価格.comの星1つのレビューのみ抽出」といった事も可能となる。この方法はまた次の機会に。。。
0 件のコメント:
コメントを投稿