【令和最新版】google-images-downloadで画像をダウンロードする

# はじめに
google-images-download はGoogle画像検索の検索結果画像を一括でダウンロードしてくれるナイスなライブラリ。インポートしてPythonスクリプトで使うだけでなく、ターミナルからコマンド的な使い方もできる。
google-images-download（[GitHub](https://github.com/hardikvasa/google-images-download)のリポジトリ）だったりgoogle_images_download（[pypi](https://pypi.org/project/google_images_download/)上の表記）だったりと表記が安定しないのが残念なところだが、それ以上に残念がことがある。Google画像検索の仕様が変わってから更新されていないため**現時点ではこれで画像をダウンロードすることができない**のだ。

# gitを使ってパッチ版をインストールする
現在のGoogle画像検索に対応したバージョンが存在するのだが、こちらはpipでインストールすることができない。
多くのサイトで紹介されているが、既存のgoogle-images-downloadをアンインストールしたうえで

```
git clone https://github.com/Joeclinton1/google-images-download.git gid-joeclinton
pip install -e gid-joeclinton
```

とする。らしい。
とはいえgitを導入していない場合も少なくないのではないだろうか。趣味で学んでいる人とか、会社のPCとか。

# gitを使わずパッチ版をインストールする

[パッチ版のGitHub](https://github.com/Joeclinton1/google-images-download)を確認する。

https://github.com/Joeclinton1/google-images-download

readmeにインストール方法が書かれているが、残念ながら正しく動かない公式版にリンクされておりそのままでは使えない。
だが、リポジトリの中にsetup.pyがあり、その中にヘルプというオプションがあることがわかり、とうとうgitを使わないインストール方法にたどり着いた。

  1. 既存のgoogle-images-downloadをインストールしていた場合はアンインストールする。  
  2. パッチ版のGitHub [https://github.com/Joeclinton1/google-images-download](https://github.com/Joeclinton1/google-images-download) からファイル一式をzipでダウンロードする。
  3. ファイルを解凍したフォルダで以下のコマンドを実行する。  
  `python setup.py install`

これでPythonは入れてあってもgitまでは入れていない会社のマシンなどでもGoogle画像検索の結果をどんどんダウンロードすることができるようになった。
あとで気づいたのだが、そのままでは使えないと書いた[公式版のインストール方法のページ](https://google-images-download.readthedocs.io/en/latest/installation.html)にほどんど同じことが書かれていた。`git clone`ではなくGUIでダウンロードしたということね。


# 使い方
## ターミナルで使う

```
googleimagesdownload -keywords "検索ワード"
```

と実行することでdownloadsフォルダの下に「検索ワード」フォルダが作られ、その中に画像が保存されていく。
都度入力するのが面倒ならバッチファイルを作ってもよい。

### オプション
多数あるので一部のみ。（ ）内は短縮形。

 - *config_file (cf)*  
　設定ファイルを指定する。設定ファイルはJSONで書く。
 - *keywords (k)*  
　キーワードを指定する。複数のときはカンマで区切る。  
　あとはGoogle検索とほぼ同じ。  
　　例　`--keywords "猫 犬"`…「猫 犬」フォルダに猫と犬の両方が含まれている画像が溜まる。
　　　　`--keywords "猫,犬"`…「猫」フォルダと「犬」フォルダにそれぞれの画像が溜まる。
　　　　`--keywords "猫 OR 犬"`…「猫 OR 犬」フォルダに猫 or 犬（論理和だから両方も含む）の画像が溜まる。  
 - *keywords_from_file (kf)*  
　キーワードのリストを指定する。リストは1行あたり1キーワードで記す。  
　拡張子は`txt`もしくは`csv`。
 - prefix_keywords (pk)  
　キーワードの接頭辞を指定する。  
　　例　`--prefix_keywords "白,黒" --keywords "猫"`…「白 猫」と「黒 猫」について実行される。
 - suffix_keywords (sk)  
　キーワードの接尾辞を指定する。prefix_keywordsの逆。
 - limit (l)  
　ダウンロードする画像の数。指定しないと100になる。  
　ダウンロードに失敗して指定した数より少なくなることがある。  
　101件以上ダウンロードするにはseleniumをインストールした上で[ChromeDriver](https://chromedriver.chromium.org/home)が必要。
 - *format (f)*  
　画像フォーマット。`jpg`、`gif`、`png`、`bmp`、`svg`、`webp`、`ico`、`raw`に対応。
 - *color (c)*  
　カラーフィルター。`red`、`orange`、`yellow`など12色に対応。
 - *color_type (ct)*  
　カラータイプ。`full-color`、`black-and-white`、`transparent`に対応。
 - *size (s)*  
　サイズ。`large`、`medium`、`icon`、`>640*480`、`>2MP`などに対応。  
　サイズ指定とメガピクセル指定は任意の値で可能なわけではない。
 - *exact_size (es)*  
　正確なサイズ。`幅, 高さ`で指定する。*size*との併用不可。
 - *aspect_ratio (a)*   
　アスペクト比。`tall`、`square`、`wide`、`panoramic`に対応。
 - *time (t)*  
　時間指定。`past-24-hours`、`past-7-days`、`past-month`、`past-year`に対応。
 - *time_range (tr)*  
　時間範囲指定。`{"time_min":"MM/DD/YYYY","time_max":"MM/DD/YYYY"}`で表記する。
 - *output_directory (0)*  
　出力ディレクトリ。すでに述べたが、未設定だと`downloads`になる。
 - *image_directory (i)*  
　画像ディレクトリ。すでに述べたが、未設定だとキーワードになる。
 - *similar_images (si)*  
　画像URLを指定し、類似画像を検索する。ローカル画像を指定することはできないっぽい。
 - *print_urls (p)*  
　画像をダウンロードするのでなくURLを表示する。
 - *language (l)*  
　言語。`English`、`Japanese`などに対応。
 - *prefix (pr)*  
　画像ファイル名の前に接頭辞を指定する。
 - *chromedriver (cd)*  
　[ChromeDriver](https://chromedriver.chromium.org/home)のパスを指定する。
 - *offset (of)*  
　ダウンロードする際の飛ばす番号。10を指定すると11番目からとなる。  
　*limit*の最大値が100なのは変わらないのでこのオプションだけで101番目以降がダウンロードできるわけではない。
 - *silent_mode (sil)*  
　サイレントモード。`True`にするとターミナル上にダウンロードしたファイル名を表記しなくなる。
 - ほかにセーフサーチの設定や非営利目的だとナンタラカンタラという使われ方の設定ができる。
 

## Pythonライブラリとして使う
Pythonスクリプトで使うときはオプションは辞書で指定する。キーワードは複数であってもリストでなくカンマで区切られたように見える一つの文字列なので注意。
サイレントモードの記載は必須ではないが最小構成としてはこんな感じだろうか。

```Python:コード1
from google_images_download import google_images_download

response = google_images_download.googleimagesdownload()
list_keyword = ["猫", "犬"]
str_keyword = ','.join(list_keyword)    # リストから"猫,犬"という文字列を作る
dic_args = {"keywords": str_keyword,
            "limit": 10,
            "silent_mode": True}
results = response.download(dic_args)
```

これで得られた`results`は要素数2のリストを返す。
1番目がダウンロードした結果。キーワードごとに分けられ、それぞれの画像のフルパスが格納される。
2番目がダウンロードに失敗した数。
次のようにすれば内容を確認できる。

```Python:コード1に追加
for keyword in list_keyword:
    print("keyword:", keyword)
    for pathname in results[0][keyword]:
        print(pathname)
    print()

print("download miss:", results[1])
```

```:結果
keyword: 猫
C:\（中略）\downloads\猫\1.1200px-a_cat_on_a_motorcycle_in_the_medina_of_tunis_20171017_131525.jpg
以下略

keyword: 犬
C:\（中略）\downloads\犬\1.img_afa0fad37e6c4d5ce34c01faf54f9e79108563.jpg
以下略

download miss: 2
```


構造がわかればダウンロードされた画像をリネームすることも難しくない。

```Python:コード1に追加
import os
for keyword in list_keyword:
    path = f"downloads\\{keyword}\\"
    for i, pathname in enumerate(results[0][keyword]):
        filename = os.path.basename(pathname)
        _, extension = os.path.splitext(filename)
        os.rename(path + filename, path + f"{keyword}_{i}{extension}")
```

きゃー猫ちゃんかわいいー！

![cats.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520216/99975cd3-185d-dca7-417e-41b747c08abf.png)

作ってみたはいいけど、キーワードにファイル名として使えない文字が含まれるとエラーになるし、連番が0から始まるので複数可実行することができないしで使い勝手が悪い。
だからといってそれらを考慮した処理をここに書くのも本質的とは言えない。リネームはダウンロードのプログラムとは別でおこなうほうがよさそうだ。`glob`を使うとか、トリミングと同様画像閲覧ソフトを使うとか。

# 終わりに
これでエｒ…いや、ディープラーニングの教師データとなる画像を容易に集められるようになった。
さまざまなシチュ…いや、ラベルに紐付けられた画像を集めてディープラーニングに挑戦しよう。