LoginSignup
33
32

More than 5 years have passed since last update.

Python3.3.1 in BottleでGoogle Custom Search APIを使って検索するだけのアプリケーションを作る

Last updated at Posted at 2013-05-23

後の人のために残します。

  • Python3の資料が少ない
  • Bottleの日本語資料も少ない

以上の理由で、無駄なところで苦労しました……。

目次

  1. この組み合わせの理由
  2. Custom searchの例
  3. Custom Searchを使って検索する部分
  4. Webアプリケーションとしてのレスポンスを返す部分
  5. 完成
  6. 感想
  7. ソースコード

この組み合わせの理由

Python3の理由

  • まず研究にPythonを使うことに決めた。Numpy, ScipyのあるPythonは情報検索の研究に向いている。
  • Python3はデフォルトのエンコーディングがutf-8なので、Python2より日本語を扱いやすい。

Bottleの理由

  • Webの研究である以上、Webアプリケーションとして実装するべきだと考えた。
  • DBは使わない。なのでマイクロフレームワークが最適。
  • PythonのマイクロフレームワークとしてFlaskBottleが有名。だがFlaskはPython3に対応していない。(2013年5月23日現在。もうじき対応するかも)追記:2013年11月29日現在、FlaskはPython3に対応しています!! いぇい!

Custom Searchの例

Custom Search APIを使って検索するサンプルコードはこちらの記事を参考。
http://qiita.com/items/92febaf8bbea541b1e36

ただし、例はPython2系列のコードとなっているので、いくつか修正する必要がある。

Custom Searchを使って検索する部分

実際に検索結果のjsonを取ってくる処理をgooglesearch.pyのsimple_search(query)という関数として定義する。

googlesearch.py
import urllib
import urllib.request
import urllib.parse
import json


def simple_search(query):
    QUERY = query
    API_KEY = 'AIzaSyBdhBWUc5W3Aco3YGPwOlS_rYM0LENl_jo'
    NUM = 1

    url = 'https://www.googleapis.com/customsearch/v1?'
    params = {
        'key': API_KEY,
        'q': QUERY,
        'cx': '013036536707430787589:_pqjad5hr1a',
        'alt': 'json',
        'lr': 'lang_ja', }
    start = 1

    for i in range(0, NUM):
        params['start'] = start
        request_url = url + urllib.parse.urlencode(params)
        try:
            response = urllib.request.urlopen(request_url)
            json_body = json.loads(response.read().decode('utf-8'))
            items = json_body['items']
        except:
            print('Error')

    return items

このファイルをapp.pyと同じディレクトリに入れる。
なお、このコードでは1ページ分、つまり検索結果10件分だけ取っている。もっと取りたい場合はparams['start']の値を変えてforループを回す。

注意点

Python3での注意。いくつかの標準ライブラリがPython2から変わっている。

  • urllib.urlopen(url)はurllib.request.urlopen(url)になった。
  • urllib.urlencode(params)はurllib.parse.urlencode(params)になった。

また、API_KEYは自分のものを使うこと。
https://code.google.com/apis/console/ で自分のGoogleアカウントでのAPIキーを取得できる。

Webアプリケーションとしてのレスポンスを返す部分

Bottleはapp.pyに、URLとhttpリクエストに対応する処理、つまりコントローラのコードを書く。

今回、view部分に使うテンプレートはMakoを使った。Makoで使うテンプレートはstatic/templatesディレクトリに入れておく。

app.py
from bottle import Bottle, route, run, static_file, request
from mako.template import Template
import googlesearch
import pdb


template = Template(filename='static/templates/index.tmpl')
app = Bottle()


@route('/static/:path#.+#', name='static')
def static(path):
    return static_file(path, root='static')


@route('/results')
def results_get():
    return template.render(items='')


@route('/results', method='POST')
def results():
    query = request.forms.decode().get('query')
    items = googlesearch.simple_search(query)
    return template.render(items=items)


@route('/')
def greet():
    return template.render(items='')
run(host='localhost', port=1234, debug=True)

ポイントは、@route('/results', method='POST')の関数で、

query = request.forms.decode().get('query')

とすること。日本語で検索するならdecode()が必要。
このやりかたはStackoverflowで見つけたのだが、日本語の資料が少ないとこういう処理をするときにマニュアルの英語を読んだりStackoverflowを探したりで無駄に手間がかかってしまうのが悲しい……。英語圏のプログラマはマルチバイト文字のことなんて考えないしもうつらい。

@route('/results', method='POST')の関数で検索結果を表示する。
POSTでなくGETメソッドで検索する方法もあると思うが、やりかたがわからないしもうPOSTでいいかなと感じている。
で、view側。

static/templates/index.tmpl
#coding: utf-8
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Subtask Search</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!-- Loading Bootstrap -->
    <link href="static/css/bootstrap.css" rel="stylesheet">

    <!-- Loading Flat UI -->
    <link href="static/css/flat-ui.css" rel="stylesheet">
    <link rel="shortcut icon" href="static/images/favicon.ico">

    <!-- HTML5 shim, for IE6-8 support of HTML5 elements. All other JS at the end of file. -->
    <!--[if lt IE 9]>
      <script src="static/js/html5shiv.js"></script>
    <![endif]-->
  </head>
  <body>
    <div class="container">
      <div class="demo-headline">
        <a href="/">
        <h1 class="demo-logo">
          Subtask Search
        </h1>
      </a>
      </div> <!-- /demo-headline -->
        <div class="span4 offset4">
                <form action="/results" method="post">
      <input type="text" name="query" value placeholder="Input your task" class="span4 offset4" />
            <input type="submit" value="Search" />
            </form>
      </div>
      <div class="span8 offset2">
        <ul class="unstyled">
        % for item in items:
        <li>
          <a href= ${item['link']}>
            ${item['title']}
          </a>
        </li>
    % endfor
  </ul>
      </div>
    </div> <!-- /container -->



    <!-- Load JS here for greater good =============================-->
    <script src="static/js/jquery-1.8.2.min.js"></script>
    <script src="static/js/jquery-ui-1.10.0.custom.min.js"></script>
    <script src="static/js/jquery.dropkick-1.0.0.js"></script>
    <script src="static/js/custom_checkbox_and_radio.js"></script>
    <script src="static/js/custom_radio.js"></script>
    <script src="static/js/jquery.tagsinput.js"></script>
    <script src="static/js/bootstrap-tooltip.js"></script>
    <script src="static/js/jquery.placeholder.js"></script>
    <script src="http://vjs.zencdn.net/c/video.js"></script>
    <script src="static/js/application.js"></script>
    <!--[if lt IE 8]>
      <script src="static/js/icon-font-ie7.js"></script>
      <script src="static/js/icon-font-ie7-24.js"></script>
    <![endif]-->
  </body>
</html>

このindex.tmplにはFlat UIを使ってきれいな見栄えにした。cssとjsはFlat UIからダウンロードしてきてstaticディレクトリに入れている。

Makoが働いているのは

       % for item in items:
        <li>
          <a href= ${item['link']}>
            ${item['title']}
          </a>
        </li>
    % endfor

の部分のみである。app.pyの

    return template.render(items=items)

で、simple_searchの結果を入れたitemsをMakoのitemsに入れて、このviewをレンダリングしている。

完成

Subtask Search.jpg
こんなのができます。

感想

マルチバイト文字の処理つらい。Python3になって楽になったはずなのにまだつらい。日本語の資料が少ないの、もっとつらい。みんなもっとノウハウ共有してほしい。

ソースコード

https://github.com/katryo/google_simple_search
にアプリケーションまるごと置いておきました。どうぞ見ていってください。

33
32
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
32