PythonでGoogle検索を自動化→CSVに出力するスクリプトを書いた

昨日の記事と同じようなネタ、タイトルだけど、今度はCustom Search APIとやらを叩いてみた。

実装にあたっては↓の記事をがっつり参考にさせていただいた。

qiita.com

やろうと思った経緯

  • しまの時刻表に掲載する時刻表等の元データが欲しい
  • Twitterのフォロワーさんに日本旅客船協会のサイトの存在を教えていただく
  • そこそこ便利だが、画面遷移多くて面倒
  • 自前でリスト作ろう

で、作った。

どうやったか

Googleで「(島名) フェリー」で検索したら、トップに運行会社がやってるページあるいはそれに近いような結果がヒットするやろ、とガバガバな仮説を立てる。

ただ、1個1個手打ちでやるのは至極しんどいので、昨日書いたスクリプトを応用して、Pythonに検索用APIを叩いてもらうことにした。

developers.google.com

画面の案内と参照元ページに従って検索エンジンインスタンスやらを作成。

参照元にあるように、API叩くのに使いやすいモジュールがあるとのことなのでインストールしておく。

$ pip install google-api-python-client

細かく解説していこうとも思ったけど、細部は前回のものとほぼ変わらないのでコード全文といくつかポイントのみ。島名のリストも元サイトがよくまとまっているので今回もそのまま使わせてもらった。

#coding:utf-8
from bs4 import BeautifulSoup
import re
import csv

# APIとの通信用
import urllib

from time import sleep
from googleapiclient.discovery import build

soup = BeautifulSoup(open("rito.html"), "lxml")
html = soup.find(class_='land-list').find_all('a')

header = ['島名', 'ページ名', 'URL']
body = []

API_KEY = '自身のAPIキー'
CUSTOM_SEARCH_ENGINE_ID = '検索エンジンのID'

service = build("customsearch", "v1", developerKey=API_KEY)

for h in html:
  text = re.split('[(|)]', h.text)
  name = text[0]
  area = text[2]
  query = area + name

  #検索
  sleep(1)
  res = service.cse().list(
    q=query + ' フェリー',
    cx=CUSTOM_SEARCH_ENGINE_ID,
    lr='lang_ja',
    num=1,
    start=1
  ).execute()

  if(res['searchInformation']['totalResults'] != '0'):
    title = res['items'][0]['title']
    url = res['items'][0]['link']
  else:
    title = ""
    url = ""
  body.append([name, title, url])
  print(name + 'の検索結果を取得')

#CSVへの出力処理
with open('data.csv', 'w') as f:
  writer = csv.writer(f)
  writer.writerow(header)
  writer.writerows(body)
print('CSVへの出力完了')

API側で(一定時間内に?)叩ける回数に制限があるので、検索する直前にsleepで間を取らせる処理を追加する必要があるのと、ヒット件数が文字列で返ってくるのに気づかなくてしばらく苦労したくらい。

で、例のごとくCSVに結果を吐き出させたので、昨日作ったものとスプレッドシート上でつなぎあわせたものがこちら。

f:id:kamonohashiy:20190509201303p:plain

検索条件がガバガバなので明らかにこれ違うだろってのもちらほらあるけど、まあこんなものかと。

検索結果を複数件取得→それらを順にクローリングさせて一番近そうな結果を出力するような実装も考えたけど、最終的に情報の内容は目視で確認しなきゃいけないので、そこまでやる必要もないかと思って見送り。

ただ考え方的にはアリかと思ったので、別の機会に取っておこうと思う。