Pythonで可愛い子の画像集め(Seleniumでスクレイピング)

## はじめに

機械学習の勉強していたとき「学習させる画像をスクレイピングで集めたいな」と思い立ちました。
機械学習・AI関連の勉強しているときに「学習データどう集めよう問題」はよくあるのではないかと思います。
本記事がそのような人たちのお役立ちになれば幸いです。

なお、記事内ではアイドルの画像を収集していますが、コマンドライン引数で収集画像を指定できる作りにしています。

## やりたいこと

* PythonでWebスクレイピングして画像収集
* Python + Seleniumで実装
* コマンドライン引数に収集したい対象を指定したら、「[プリ画像](https://prcm.jp/)」サイトから画像をダウンロード

以下のように実行すると、

```
python XXX.py 乃木坂46 100
```

このように画像が集まります。

![nogizaka.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2080707/424f97e9-9f4c-0a8b-8a31-a639fb13a631.png)

## 環境

* MacBookPro M1
* Python 3.9.7
* Selenium 3.141.0

## 方針

* コマンドライン引数に「収集したい対象」と「徘徊するページ数」を指定
* 画像はカレントディレクトリ配下のimages/[収集したい対象]ディレクトリに保存
* 複数回実行すると、前回のものを全削除して、再度ダウンロード

## 注意事項

Webスクレイピングするときの一般的なお話ですが、
* 著作権や利用規約は事前に確認する
* サーバに負荷をかけすぎないよう間隔をあけてアクセスする
* robots.txtも確認しておく

https://docs.pyq.jp/column/crawler.html

## Selenium Pythonのキホン

### 1. インストール

```python
pip install selenium
```

### 2. 使い方

```python
# モジュールのimport
from selenium import webdriver

# ブラウザ操作のインスタンスを作成
# Firefoxを使用する場合
driver = webdriver.Firefox()
# Chromeを使用する場合
driver = webdriver.Chrome()

# 指定したURLへアクセス
driver.get('http://〜')

# ページ内の要素を取得(あくまで一例)
driver.find_element_by_id('XXX')
driver.find_elements_by_class_name('XXX')
driver.find_element_by_css_selector('XXX')

# ブラウザを閉じる
driver.quit()
```

## 可愛い子の画像集め(コード)

### 1. モジュールのインポート

```python
import os
import shutil
import sys
import time
import urllib.request

from selenium import webdriver
```

### 2. main処理

```python
def main():
    # 引数チェック
    target = ''
    per_page = 0
    try:
        target = sys.argv[1]
        per_page = int(sys.argv[2])
    except IndexError:
        print('引数に「収集したい対象」と「徘徊するページ数」を指定してください。')
        exit()
    except ValueError:
        print('引数に「収集したい対象」と「徘徊するページ数」を指定してください。')
        exit()

    # プリ画像のURL
    BASE_URL = 'https://prcm.jp'

    # 保存先のディレクトリ
    save_dir = 'images/' + target
    if not os.path.exists(save_dir):
        os.mkdir(save_dir)
    else:
        # すでにディレクトリがあったら全削除して再作成
        shutil.rmtree(save_dir)
        os.mkdir(save_dir)

    # ブラウザ操作のインスタンス作成(Firefox)
    driver = webdriver.Firefox()
    # リクエスト間隔
    wait_time = 1
    try:
        # プリ画像のTOPページを表示し、検索ボックスに指定したキーワードを入力・検索
        driver.get(BASE_URL)
        driver.find_element_by_css_selector('.search__input').send_keys(target)
        driver.find_element_by_css_selector('.search__btn').click()
        time.sleep(wait_time)
        # 画像一覧の要素を取得し、画像をダウンロード
        for i in range(per_page):
            image_list = driver.find_element_by_id('imglist_container').find_elements_by_class_name('list-pic__item')
            for image in image_list:
                image_url = image.find_element_by_css_selector('a > div > img').get_attribute('src')
                file_path = save_dir + '/' + image_url.split('/')[-1]
                data = urllib.request.urlopen(image_url).read()
                with open(file_path, 'wb') as f:
                    f.write(data)
            # 次のページへアクセス
            page_navigation = driver.find_element_by_class_name('page-navigation')
            next_link = page_navigation.find_element_by_class_name('page-navigation__next')
            link_url = next_link.find_element_by_css_selector('a').get_attribute('href')
            driver.get(link_url)
            time.sleep(wait_time)
    except Exception as e:
        print('エラー : ', e)
        driver.quit()
        exit()

    # ブラウザを閉じる
    driver.quit()


if __name__ == '__main__':
    main()
```

上記コードを以下のように実行すると、

```
python XXX.py 乃木坂46 100
```

「images/乃木坂46」ディレクトリの配下に、プリ画像からダウンロードした画像が保存されました。

## まとめ

今回はアイドル画像を収集しましたが、やっていることは「プリ画像の検索ボックスにキーワードを入力→検索→画像をダウンロード」しているだけなので、キーワードを変えれば他のいろいろな画像を収集できます。
ここでダウンロードしたアイドル画像で、機械学習・AIの勉強が捗りそうです。