2014/09/11

無料でGoogle検索を自動化する

プログラムから自動で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メニューを選択

APIの一覧からCustom Search APIを探し、右のボタンを押す。
APIの有効化

ちなみに、100リクエスト/日以上検索したい場合は、API名を選択後に表示される画面で割り当てを選択し・・・
API割り当ての選択

ここのSet billable limitsから、1日のリクエスト可能数を引き上げる事ができる。(※プロジェクトの課金を有効にしておく必要がある。)
enter image description here

続いてAPIにアクセスするためのキーを取得する。「APIと認証」から「認証情報」を選択する。
認証情報

次に表示される画面で、「新しいキーを作成」から「サーバーキー」を選択する。OAuthは、例えばユーザー情報を取得するようなAPIを使用する時に選択する。今回は検索のみを使用するので、サーバーキーでOKだ。
新しいサーバーキーの作成

許可IPアドレスの設定は今回空欄とした。特定のIPアドレスのサーバーからのみキーを有効としたい場合は設定する。
許可IPアドレスの設定

これでキーが作成できた。このキーはプログラムからAPIへ接続する際に使用する。
APIキーの完成

Google Custom Searchを作成する

APIキーを取得したら次は Google Custom Search で検索エンジンを作成する。Custom Search APIはここで作成した検索エンジンを操作するAPIだ。

Google Custom Search へアクセスし、新しい検索エンジンを作る。
新しい検索エンジンの作成

検索対象のサイトドメインを登録する。かならず1つのドメインを指定する必要がある。今回はとりあえず kakaku.com(あとで変更する) を入力し、検索エンジンの名前を指定。
ドメインの登録

これで検索エンジンが完成。コントロールパネルへアクセスする。
検索エンジンの完成

ここから検索エンジンのIDを取得しておく、IDもAPIキー同様にプログラムからAPIへアクセスする場合に必要。
enter image description here

今回は、価格.comのレビューのみを取得する事が目的なので、その他のページがヒットしないよう、レビューページのURLのみをターゲットにする。対象サイトを選択して・・・
enter image description here

レビューページのURLを入力する。商品IDなど動的に変わる部分は*でワイルドカード指定ができる。
enter image description here

これで、価格.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 件のコメント:

コメントを投稿