Pythonで画像自動検索＆規則ファイル名で自動保存

# やろうとしてること
指定の検索ワードで、画像を検索し、規則ファイル名で自動保存

### なぜこんなことをしようと思ったか
https://qiita.com/horita_toshiki_r0/items/8bf978bdaa7efb880117

上記の学習のための素材集めのため
「ナルト」「ルフィー」それぞれの訓練用データを10枚ずつ集める必要がありました。

また、学習用データ10枚ずつだといずれにせよ少ないので、学習用データ収集の自動化は必須

# 書いたコード

```Python:Python
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import urllib.request
import time

# 検索ワード
search_word = 'ルフィー 顔 画像'

# 画像保存先のフォルダ
save_dir = './luffy_faces/'

# webdriverのパス
webdriver_path = './chromedriver/chromedriver.exe'

# webdriverのオプション
options = webdriver.ChromeOptions()
#options.add_argument('--headless')

# webdriverの起動
print('Starting ChromeDriver...')
driver = webdriver.Chrome(webdriver_path, options=options)

# Google画像検索を開く
driver.get('https://www.google.co.jp/imghp')

# 検索ワードを入力して検索する
search_box = driver.find_element_by_name('q')
search_box.send_keys(search_word)
search_box.send_keys(Keys.RETURN)

# 画像をダウンロードする
for i in range(10):
    try:
        # 画像をクリックして拡大表示する
        images = driver.find_elements_by_css_selector('.rg_i')
        images[i].click()
        time.sleep(1)

        # 画像のURLを取得して保存する
        image_url = driver.find_element_by_css_selector('.n3VNCb').get_attribute('src')
        urllib.request.urlretrieve(image_url, f'{save_dir}luffy_{i}.jpg')
        print(f'ルフィーの顔画像{i}をダウンロードしました。')

        # 戻るボタンをクリックして戻る
        driver.back()
        time.sleep(1)

    except Exception as e:
        print("Error occurred:", e)
        continue

# webdriverを閉じる
driver.quit()
```



```:出力
Starting ChromeDriver...
ルフィーの顔画像0をダウンロードしました。
ルフィーの顔画像1をダウンロードしました。
ルフィーの顔画像2をダウンロードしました。
ルフィーの顔画像3をダウンロードしました。
ルフィーの顔画像4をダウンロードしました。
ルフィーの顔画像5をダウンロードしました。
ルフィーの顔画像6をダウンロードしました。
ルフィーの顔画像7をダウンロードしました。
ルフィーの顔画像8をダウンロードしました。
ルフィーの顔画像9をダウンロードしました。
```

# ぶつかったちょっとした壁

Python初心者のため、ほぼ本件とは無関係の極めて基礎的なことです。

### １．chromedriverは別途用意するもの
はじめchromedriverの存在を理解しておらず、「chrome」のことと勘違いしていました。

https://aiacademy.jp/media/?p=346#:~:text=ChromeDriver%E3%81%AFChrome%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%82%92%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%A7%E5%8B%95%E3%81%8B%E3%81%99%E7%82%BA%E3%81%AE%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90%E3%83%BC%E3%81%A7%E3%81%99%E3%80%82&text=Selenium%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%AF%E6%AC%A1,%E3%81%93%E3%81%A8%E3%81%A7%E3%80%81%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E5%87%BA%E6%9D%A5%E3%81%BE%E3%81%99%E3%80%82&text=Chrome%20Driver%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%AF%E4%B8%8B%E8%A8%98%E3%83%AA%E3%83%B3%E3%82%AF%E3%81%8B%E3%82%89%E9%A3%9B%E3%81%B9%E3%81%BE%E3%81%99%E3%80%82
>ChromeDriverはChromeブラウザをプログラムで動かす為のドライバーです。

### ２．フォルダは生成コマンドを書くか事前に用意する必要がある

```Python:保存先指定
save_dir = './luffy_faces/'
```
ここで勝手にフォルダ生成されるわけではありません（当たり前）
フォルダ内状態で実行し、当然ですが画像のダウンロードがされず、数分迷いました。

```Python:現
except Exception as e:
        print("Error occurred:", e)
        continue
```
最初上記を下記のように書いていました

```Python:旧
except Exception as e:
        continue
```

上記だとエラーメッセージが出ないので、きちんとエラーメッセージが出るようにするということの重要性も認識。

```Python:エラーログ出力
print("Error occurred:", e)
```

上記1行を書くだけで、なぜダウンロードがされずにプログラムが終了してしまうのかが一発で分かります。

```:エラー
Error occurred: [Errno 2] No such file or directory: './luffy_faces/luffy_0.jpg'
```


# ざっくりプログラムをひも解く

### 必要ライブラリインポート

```Python:Python
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import urllib.request
```

「Keys」・・・画像検索時にキーボード入力をエミュレートできる
「urllib.request」・・・requestモジュールによって、指定urlからファイルをダウンロードできる

### chromedriver取得


```Python:Python
driver = webdriver.Chrome(webdriver_path, options=options)

driver.get('https://www.google.co.jp/imghp')
```

'driever'オブジェクトの'get'メソッドは、指定urlのwebページを開くメソッド

### キーワード検索

```Python:Python
# 検索ワードを入力して検索する
search_box = driver.find_element_by_name('q')
search_box.send_keys(search_word)
search_box.send_keys(Keys.RETURN)
```

driverオブジェクトのfind_element_by_name()メソッドを呼び出して、Google検索バーを取得しています。このとき、引数に検索バーのname属性である'q'を指定。

send_keys()メソッドを使用して、検索ワードを検索バーに入力
↓
KeysモジュールからRETURN属性を取得して、send_keys()メソッドを呼び出すことで、Enterキーを押下して検索を実行

### 表示上位10件の画像を指定フォルダに命名規則に則り保存
```Python:Python
for i in range(10):
    try:
        # 画像をクリックして拡大表示する
        images = driver.find_elements_by_css_selector('.rg_i')
        images[i].click()
        time.sleep(1)

        # 画像のURLを取得して保存する
        image_url = driver.find_element_by_css_selector('.n3VNCb').get_attribute('src')
        urllib.request.urlretrieve(image_url, f'{save_dir}luffy_{i}.jpg')
        print(f'ルフィーの顔画像{i}をダウンロードしました。')

        # 戻るボタンをクリックして戻る
        driver.back()
        time.sleep(1)

    except Exception as e:
        print("Error occurred:", e)
        continue

```

```Python:検索結果から画像要素取得⇒拡大表示
images = driver.find_elements_by_css_selector('.rg_i')
images[i].click()
time.sleep(1)
```
driverオブジェクトから.rg_iというCSSセレクタにマッチする全ての画像の要素を取得し、imagesという変数に代入。


'.click()'メソッドにより、i番目の画像を拡大表示
'time.sleep()'メソッドで拡大されるのを待つ
```Python:画像のURLを取得して保存する
image_url = driver.find_element_by_css_selector('.n3VNCb').get_attribute('src')
urllib.request.urlretrieve(image_url, f'{save_dir}luffy_{i}.jpg')
print(f'ルフィーの顔画像{i}をダウンロードしました。')
```

driverオブジェクトから、拡大表示された画像のURLを取得し、image_urlという変数に代入しています。find_element_by_css_selector()メソッドを使って、.n3VNCbというCSSセレクタにマッチする要素を取得し、get_attribute('src')でその要素のsrc属性（つまり、画像のURL）を取得。