google apiでwebクローラを作る

google apiを使ってpythonでクローラを作ろうとしたら,意外と面倒だったのでメモしておく.

API keyを登録する

Google Could Platformにアクセスし,プロジェクトを作成してapi keyを登録する.

アクセスするとポップアップが立ち上がり, 利用規約に従うかどうかを聞かれるのでOKならYesを選択する.

次にページのヘッダーにあるSelect a projectの部分をクリックし,Create projectの+マークをクリック.

Project nameを適当につけて (画像はデフォルトのMy Project),Createでプロジェクトを作成する. create project

createしてしばらく待つと,プロジェクト内のダッシュボードが描画される.

次にAPI keyを作成する.

サイドバーのAPI ManagerからCredentialsをクリックし,Create credentials→API keyで作成できる. 作成時にAPI keyを使用するipの制限などができるRESTRICT KEYの設定があるので,必要ならば適宜設定を行う.

api key setting ※ 上の図はapi keyの設定画面.keyの使用に制限をかけていないと警告のため黄色い三角にビックリマークが表示されるようだ.

Custom search engine IDを作成する

Custom Search - Create CSEからCustom search engine (CSE) を作成する.
Site to searchの部分にはとりあえずwww.example.comのExample Domainのページでも登録しておく.本来は検索をしたいサイトを登録するが,Webページ全体を検索対象としたいので無害そうなドメインを登録する.(別にCSE設定時に選択しなければよいだけだが)

CSE Creation search engineの名前を決めて,サイト下にあるCreateを押して登録.登録完了のページに遷移するので,そこでControl Panelのボタンをクリック.遷移先のDetailsのSearch engine IDをクリックしてIDの文字列を確認する.また,その下にあるImage searchのトグルをONにして, Site to searchのプルダウンメニューをSearch only included sitesからSearch the entire web but emphasize included sitesに変更する.

CSE Settings

画像検索用のスクリプトを組む

今回はこんな感じでpythonで書いた.

#!/usr/bin/env python3
#-*- coding:utf-8 -*-

import argparse
import json
import os
import sys

from urllib.request import urlopen
from urllib.request import build_opener
from urllib.request import Request

from googleapiclient.discovery import build

# keywordの画像リンクを探索
def url_search(keyword, filetype, num):
    """Search url.
    Args:
        keyword(str): Keyword for search.
        filetype(str): Filetype.
        num(int): Number of search result to return.
    """
    service = build("customsearch", "v1", developerKey=<YOUR_API_KEY>)
    urls = []
    offset = 1
    limit = 10  # "num" parameters description: Valid values are integers between 1 and 10, inclusive.
    if num < limit:
        limit = num
    while True:
        res = service.cse().list(
            cx=<YOUR_CSE_ID>,
            searchType='image',
            q=keyword,
            num=limit,
            start=offset,
            fileType=filetype,
            rights='cc_publicdomain cc_attribute cc_sharealike cc_noncommercial cc_nonderived',
        ).execute()
        if 'items' in res:
            urls += [item['link'] for item in res['items']]
        offset += limit
        if offset >= num:
            break
    return urls


def url_download(keyword, urls):
    """Download image resource from url."""
    # Make directory if it does not exist.
    if os.path.exists(keyword)==False:
        os.mkdir(keyword)
    print("Download Start...")
    opener = build_opener()
    # URLの数だけ画像DL
    for i, url in enumerate(urls):
        try:
            fn, ext = os.path.splitext(url)
            req = Request(url, headers={"User-Agent" : "Magic Browser"})
            img_file = open(keyword + "/" + str(i) + ext, "wb")
            img_file.write(opener.open(req).read())
            img_file.close()
            print("DL Image Link:" + str(i + 1))
        except:
            continue


def main(*args, **kwargs):
    """Main function."""
    arg = args[0]
    keyword = arg.keyword
    filetype = arg.filetype
    num = arg.num
    urls = url_search(keyword, filetype, num=num)
    url_download(keyword, urls)
    print("End...")


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--keyword', '-k', type=str,
                        help='Retrieval keyword.')
    parser.add_argument('--filetype', '-f', type=str,
                        help='Filetype')
    parser.add_argument('--num', '-n', type=int, default=1,
                        help='Number of images you want to download.')
    args = parser.parse_args()
    sys.exit(main(args))

上のスクリプトを自分のAPI keyとCSE idに書き換えて実行する.

実行例:

$ python get_image.py -k hoge -n 10

hoge

確かに画像が10枚ダウンロードされた.

今回使用したスクリプトでは検索のパラメータとして

res = service.cse().list(
    cx=<YOUR_CSE_ID>,
    searchType='image',
    q=keyword,
    num=limit,
    start=offset,
    fileType=filetype,
    rights='cc_publicdomain cc_attribute cc_sharealike cc_noncommercial cc_nonderived',
).execute()

のような感じで指定したが,パラメータの詳細は

$ python
>>> from googleapiclient.discovery import build
>>> service = build("customsearch", "v1", developerKey="hoge")
>>> help(service.cse().list)

のようにして確認ができる.

参考