Python

【コピペOKです】Pythonを使って自動でGoogle画像を収集する方法を徹底解説!

【コピペOKです】Pythonを使って自動でGoogle画像を収集する方法を徹底解説!

こんにちは、さすを(@sasuwo0409)です。

いきなりですが、

画像を自動で収集したい!

Pythonを使って形になるものを作ってみたい!

と思ってはいませんか?

今回の記事は、Pythonを使って自動でGoogle画像を収集する方法を解説してみたいと思います。

この記事を読めば、効率的に画像を収集できるようになります。

それでは本文をどうぞ。

困っている人
困っている人

画像を大量に集めなきゃいけないんだけど、ひとつひとつ手でやるのめんどくさいのよね、、

もっと効率的に集める方法はないかしら、、

さすを
さすを

この悩みを解決します!

この記事を読むとわかること:

Pythonを使って自動でGoogle画像を収集する方法

筆者の情報:

  • 現役システムエンジニア 兼 ブロガー
  • 過去に6,000万のPython案件を受注
  • 最近ハマっていることは機械学習

注意:
保存する画像によっては著作権に引っかかる可能性があります。
各画像の規約を守って、正しく活用しましょう。

※お金がかかってもいいから、少しでも早くPythonスキルを身につけたい方は、TechAcademy(テックアカデミー)のPythonコースがおすすめです。
エンジニアになれば、受講料は1か月もあれば回収できるので、問題なしです。
本気でPythonスキルを身につけたい方は、スクールで一気にスキルを身に着けるのもありでしょう。

>>TechAcademy(テックアカデミー)のPythonコースはこちら

スポンサーリンク

1.Pythonを使って自動でGoogle画像を収集する方法

今回はGoogle Colaboratory上でプログラムを動かしていきます。

Google Colaboratoryの使い方については「【3分で解決!】Google Colaboratoryの使い方【無料ですぐにPythonを使えます】」で解説しています。

Pythonを使って自動でGoogle画像を収集するための手順は以下の3ステップです。

  1. 画像を格納するフォルダを作成する
  2. 必要なライブラリをインストールする
  3. 画像を収集するプログラムを書く

その①:画像を格納するフォルダを作成する

今回は、プログラムが格納されているGoogle Colabフォルダ直下にimgフォルダを作成しています。また、imgフォルダの中にurlフォルダを作っています。

Google Colab
—–get_pic.ipnb(これから作るスクリプト)
—–img
———–url

フォルダ構成を変更してもOKですが、後述するプログラムの保存先フォルダ名が変わるので注意してください。

その②:必要なライブラリをインストールする

プログラムを動かすうえで必要なものが2つあります。以下のコードを実行し、インストールしましょう。

pip install selenium

selenium:Webブラウザで行うクリック操作やキーボード入力などをプログラム上から自動で操作できるようにしたライブラリ

!apt install chromium-chromedriver

chromium-chromedriver :Chromeブラウザをプログラムで動かす為のドライバ

その③:画像を収集するプログラムを書く

Google画像を自動で収集するプログラムは下記の通りです。

#ドライブをマウントする
from google.colab import drive
drive.mount('/content/drive')

補足:
上記のコマンドを実行すると、以下の画面が現れます。手順通りに操作すればOKです。

1.URLを押下

図1:マウントの手順①
図1:マウントの手順①

2.希望のアカウントを選択

図2:マウントの手順②
図2:マウントの手順②

3.ログインを押下

図3:マウントの手順③
図3:マウントの手順③

4.コードをコピーし、「Enter your authorization code」に入力

図4:マウントの手順④
図4:マウントの手順④
#カレントディレクトリに移動
%cd "/content/drive/My Drive/Google Colab"
import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import os
import time
import datetime
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import ElementClickInterceptedException
 
tm_start = time.time()            #処理時間計測用
dt_now = datetime.datetime.now()  # 現在日時
dt_date_str = dt_now.strftime('%Y/%m/%d %H:%M')
print(dt_date_str)
 
QUERY = '犬 フリー'                        # 検索ワード
LIMIT_DL_NUM = 100                          # ダウンロード数の上限
SAVE_DIR = 'img/dog_'                        # 出力フォルダへのパス(フォルダがない場合は自動生成する)
FILE_NAME = 'dog_'                          # ファイル名(ファイル名の後ろに0からの連番と拡張子が付く)
TIMEOUT = 60                                # 要素検索のタイムアウト(秒)
ACCESS_WAIT = 1                             # アクセスする間隔(秒)
RETRY_NUM = 3                               # リトライ回数(クリック、requests)
DRIVER_PATH = '/usr/bin/chromedriver'       # chromedriver.exeへのパス
 
# Chromeをヘッドレスモードで起動
options = Options()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--start-fullscreen')
options.add_argument('--disable-plugins')
options.add_argument('--disable-extensions')
driver = webdriver.Chrome(DRIVER_PATH, options=options)
 
# タイムアウト設定
driver.implicitly_wait(TIMEOUT)
 
tm_driver = time.time()
print('WebDriver起動完了', f'{tm_driver - tm_start:.1f}s')
 
# Google画像検索ページを取得
url = f'https://www.google.com/search?q={QUERY}&tbm=isch'
driver.get(url)
 
tm_geturl = time.time()
print('Google画像検索ページ取得', f'{tm_geturl - tm_driver:.1f}s')
 
tmb_elems = driver.find_elements_by_css_selector('#islmp img')
tmb_alts = [tmb.get_attribute('alt') for tmb in tmb_elems]
 
count = len(tmb_alts) - tmb_alts.count('')
print(count)
 
while count < LIMIT_DL_NUM:
    # ページの一番下へスクロールして新しいサムネイル画像を表示させる
    driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')
    time.sleep(1)
 
    # サムネイル画像取得
    tmb_elems = driver.find_elements_by_css_selector('#islmp img')
    tmb_alts = [tmb.get_attribute('alt') for tmb in tmb_elems]
 
    count = len(tmb_alts) - tmb_alts.count('')
    print(count)  
 
# サムネイル画像をクリックすると表示される領域を取得
imgframe_elem = driver.find_element_by_id('islsp')
 
# 出力フォルダ作成
os.makedirs(SAVE_DIR, exist_ok=True)
 
# HTTPヘッダ作成
HTTP_HEADERS = {'User-Agent': driver.execute_script('return navigator.userAgent;')}
print(HTTP_HEADERS)           
            
# ダウンロード対象のファイル拡張子
IMG_EXTS = ('.jpg', '.jpeg', '.png', '.gif')
 
# 拡張子を取得
def get_extension(url):
    url_lower = url.lower()
    for img_ext in IMG_EXTS:
        if img_ext in url_lower:
            extension = '.jpg' if img_ext == '.jpeg' else img_ext
            break
    else:
        extension = ''
    return extension
 
# urlの画像を取得しファイルへ書き込む
def download_image(url, path, loop):
    result = False
    for i in range(loop):
        try:
            r = requests.get(url, headers=HTTP_HEADERS, stream=True, timeout=10)
            r.raise_for_status()
            with open(path, 'wb') as f:
                f.write(r.content)

        except requests.exceptions.SSLError:
            print('***** SSL エラー')
            break  # リトライしない
        except requests.exceptions.RequestException as e:
            print(f'***** requests エラー({e}): {i + 1}/{RETRY_NUM}')
            time.sleep(1)
        else:
            result = True
            break  # try成功
    return result
 
tm_thumbnails = time.time()
print('サムネイル画像取得', f'{tm_thumbnails - tm_geturl:.1f}s')
 
# ダウンロード
EXCLUSION_URL = 'https://lh3.googleusercontent.com/'  # 除外対象url
count = 0
url_list = []
for tmb_elem, tmb_alt in zip(tmb_elems, tmb_alts):
     
    if tmb_alt == '':
        continue
 
    print(f'{count}: {tmb_alt}')
 
    for i in range(RETRY_NUM):
        try:
            # サムネイル画像をクリック
            tmb_elem.click()
        except ElementClickInterceptedException:
            print(f'***** click エラー: {i + 1}/{RETRY_NUM}')
            driver.execute_script('arguments[0].scrollIntoView(true);', tmb_elem)
            time.sleep(1)
        else:
            break  # try成功
    else:
        print('***** キャンセル')
        continue  # リトライ失敗
         
    # アクセス負荷軽減用のウェイト
    time.sleep(ACCESS_WAIT)
     
    alt = tmb_alt.replace("'", "\\'")
    try:
        img_elem = imgframe_elem.find_element_by_css_selector(f'img[alt=\'{alt}\']')
    except NoSuchElementException:
        print('***** img要素検索エラー')
        print('***** キャンセル')
        continue
 
    # url取得
    tmb_url = tmb_elem.get_attribute('src')  # サムネイル画像のsrc属性値
 
    for i in range(RETRY_NUM):
        url = img_elem.get_attribute('src')
        if EXCLUSION_URL in url:
            print('***** 除外対象url')
            url = ''
            break
        elif url == tmb_url:  # src属性値が遷移するまでリトライ
            print(f'***** urlチェック: {i + 1}/{RETRY_NUM}')
            time.sleep(1)
            url = ''
        else:
            break
 
    if url == '':
        print('***** キャンセル')
        continue
 
    # 画像を取得しファイルへ保存
    ext = get_extension(url)
    if ext == '':
        print(f'***** urlに拡張子が含まれていないのでキャンセル')
        print(f'{url}')
        continue
 
    filename = f'{FILE_NAME}{count}{ext}'
    path = SAVE_DIR + '/' + filename
    result = download_image(url, path, RETRY_NUM)
    if result == False:
        print('***** キャンセル')
        continue
    url_list.append(f'{filename}: {url}')
 
    # ダウンロード数の更新と終了判定
    count += 1
    if count >= LIMIT_DL_NUM:
        break
 
tm_end = time.time()
print('ダウンロード', f'{tm_end - tm_thumbnails:.1f}s')
print('------------------------------------')
total = tm_end - tm_start
total_str = f'トータル時間: {total:.1f}s({total/60:.2f}min)'
count_str = f'ダウンロード数: {count}'
print(total_str)
print(count_str)
 
# urlをファイルへ保存
path = SAVE_DIR + '/url/' + '_url.txt'
with open(path, 'w', encoding='utf-8') as f:
    f.write(dt_date_str + '\n')
    f.write(total_str + '\n')
    f.write(count_str + '\n')
    f.write('\n'.join(url_list))
 
driver.quit()

実行結果:

図5:実行結果
図5:実行結果

機械学習をするなら画像データを水増ししよう

機械学習をするために画像を収集しているのであれば、画像枚数が多ければ多いほど精度はあがりますが、画像枚数を増やすのにも限度はありますよね。

そこで、おすすめなのがデータの水増しです。

データの水増し:
データを左右反転、色の変更、拡張、収縮、回転し、データの数を増やすこと。

ですので、機械学習のために画像を収集しているのであれば、データの水増しをしておきましょう。

画像を反転、グレー画像に変更したソースコードを以下に貼っておくので、活用してください。

#反転画像を保存する処理

import cv2
import os
import time
import datetime

tm_start = time.time()            #処理時間計測用
dt_now = datetime.datetime.now()  # 現在日時
dt_date_str = dt_now.strftime('%Y/%m/%d %H:%M')
print(dt_date_str)

path = 'img/dog'

files = os.listdir(path)

files_file =  [f for f in files if os.path.isfile(os.path.join(path, f))]

for y_pic in files_file:

  img = cv2.imread(path + "/" + y_pic)

  y = cv2.flip(img,1)

  cv2.imwrite(path + "/y_" + y_pic,y)

tm_end = time.time()
print('処理完了')
print('------------------------------------')
total = tm_end - tm_start
total_str = f'トータル時間: {total:.1f}s({total/60:.2f}min)'
print(total_str)
図6:反転画像
図6:反転画像
#白黒画像を保存する処理

import cv2
import os
import time
import datetime

tm_start = time.time()            #処理時間計測用
dt_now = datetime.datetime.now()  # 現在日時
dt_date_str = dt_now.strftime('%Y/%m/%d %H:%M')
print(dt_date_str)

path ='img/dog'

files = os.listdir(path)

files_file =  [f for f in files if os.path.isfile(os.path.join(path, f))]

print(files_file)


for y_pic in files_file:

  img = cv2.imread(path + '/' + y_pic)

  img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

  cv2.imwrite(path + '/gray_' + y_pic,img_gray)

tm_end = time.time()
print('処理完了')
print('------------------------------------')
total = tm_end - tm_start
total_str = f'トータル時間: {total:.1f}s({total/60:.2f}min)'
print(total_str)
図7:白黒画像
図7:白黒画像

最後に:機械に働かせて自分は休もう

Google Colaboratoryを使って自動でGoogle画像を収集する方法を解説してきました。

この記事を読んでいるということは、めんどくさい作業を自動化して、自分の時間を生み出そうとしている「時間の大切さを知っている人」だと思います。

『Time is not money(時間はお金では買えない)』

という言葉を忘れずに、これからもコツコツと自分の時間が増えるようプログラムを書いていこうと思います。

この記事が少しでも役に立っていたらうれしいです!

それでは!

参考にした記事:PythonスクレイピングでGoogle画像検索ページから画像を取得


コメント

タイトルとURLをコピーしました