gologiusの巣

プログラミングなどの技術メモです。誰かの役に立てるとうれしいです。

ランダムな画像をDLする 【Python, WIkipedia, Google API】

毎日新しい知識を取り入れたい・・・

ランダムなWikipediaの記事を、画像付きで紹介する、

そんな仕組みを作ってみましょう。

クリスマスだけどな!!!

やること

そんなわけで

  • Wikipediaで適当にワード検索する
  • 検索したワードでGoogle画像検索する
  • 画像をダウンロードする

この三つ、やっていきましょう。

使用したスクリプトは下記URLにおいてます。

適当な画像をDLします · GitHub

1.Wikipediaでランダム記事取得

特定のURLにアクセスすると、ランダムな記事データが取得できます。 取得した記事のタイトルを、画像検索のキーワードとして使用します。

ランダムな記事取得には以下のURLを使用します

https://ja.wikipedia.org/w/api.php?action=query&list=random&rnlimit=1&rnnamespace=0&format=json
パラメータ名 内容
action=query 記事取得
list=random ランダムに記事取得
rnlimit=1 何件取得するか
rnnamespace=0 記事だけ取得する※
format=json JSONで取得するために指定。XMLなどでもOK

※詳しくは以下ページ参照。これを指定しないと誰かのノートやユーザーページも抽出される。邪魔。

https://en.wikipedia.org/wiki/Wikipedia:Namespace

アクセスして取得したJSONはこんな感じ f:id:gologius:20181224162311p:plain

idは記事に振られているIDです。 下記のようなURLでアクセスできます。

https://ja.wikipedia.org/?curid=214545

実際にPythonに落とし込むとこれだけでできます。

import requests

WIKI_RANDOM_URL = 'https://ja.wikipedia.org/w/api.php?action=query&list=random&rnlimit=1&rnnamespace=0&format=json'
response = requests.get(WIKI_RANDOM_URL)
article = response.json()['query']['random']

art_id = article[0]['id']
art_title = article[0]['title']

2.Googleで画像検索

では次に、取得した記事タイトルで画像検索をします。 流れは以下のようになります

  1. (前準備)APIキーの取得
  2. (前準備)カスタム検索の作成(厳密にはsearchidが欲しい)
  3. 画像検索をして、画像URLを取得する
  4. 取得したURLへアクセスし、画像をダウンロードする

前準備

Google画像検索APIを使用するためには前準備が必要になります。 下記URLを参考に取得してください(下記スクリプトAPIKEY,SEARCH_IDに該当する部分です)。

urashita.com

ちなみに私はカスタム画像検索の設定項目「ウェブ全体を検索」を「オン」にしてなかったので、 画像検索でエラーになる凡ミスを起こしました。 また当たり前ですが「画像検索」が「オン」になってないと利用できないので気を付けてください。 f:id:gologius:20181224162342p:plain

画像検索

使用するにはパッケージのインストールが必要になります。

pip install --upgrade google-api-python-client

Google画像検索は以下のようなPythonスクリプトで実行可能です。

※実際の機能としては、service.cse().list()の引数startをインクリメントすることで、 さらに検索結果を取得することができます。 ただし、今回は大量の画像が欲しいわけではないので無視します。

from googleapiclient.discovery import build

APIKEY="your google api key"
SEARCH_ID = "your search id"

# Googleでそのキーワードでイメージ検索する
service = build("customsearch", "v1", developerKey=API_KEY)
responses = []
try:
    response = service.cse().list(q=art_title,cx=SEARCH_ID,num=5,start=1,searchType='image').execute()
    responses.append(response)
except Exception as e:
    print("gmail api error")
    print(e)

#URLのみ抽出
img_urls = []
for r in responses:
    for i in r['items']:
        img_urls.append(i['link'])

3.画像ダウンロード

urllib使用すれば余裕です。 気を付けないといけないのは、「URLにパラメータがついたまま」の場合があることです。 ファイル名をWEB上のファイルと同じものに使用とした場合に問題になります。 適当にパースしてあげましょう。

# 画像をダウンロードする
filepaths = []
for url in img_urls:
    try:
        # ファイル名だけ取り出す
        filename = url.split('/')[-1]
        idx = filename.find("?")
        if idx >= 0:
            filename = filename[:idx]

        filepath = DOWNLOAD_PATH + "\\" + art_title + "_"+  filename
        urllib.request.urlretrieve(url, filepath)        
        filepaths.append(filepath)
        print(filepath)

    except Exception as e:
        print("image download error")
        print(e)

上記のスクリプトだと

  • 画像ファイル以外の場合 → 画像ファイルでないものがDLされてしまう
  • アクセス拒否されている場合(403エラー)→ 例外で落ちる となります。注意してください。

真面目にやるなら

  1. URLにアクセス
  2. ファイルが画像か確認
  3. DLを試みる
  4. 成功したら(1.)に戻る * 指定回数繰り返す

なんでしょうね。

注意点

以下注意点

  • サーバー負荷がかからぬように、節度を持ってアクセスしましょう
  • どんな画像がヒットするかわかりません(エログロ個人写真etc)。私はスクリプトを実行したことによる責任は一切持ちません
  • 上記の話があるのでTwitterBotにするのはおすすめしません

まとめ

スクリプトはこちら(記事先頭と同じURLです)

https://gist.github.com/gologius/dffd310024fdc621ec78644a3362a3d1

ランダムな画像をDLする仕組みを構築してみました。

私は毎日一回、メールでその内容を受信しています(GmailAPIで画像添付する方法はまた後日・・・)

一日の始まりが少しだけ面白くなったような、なってないような・・・