0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Google画像検索の各画像をスクリーンショットで保存する (Python, Selenium)

Last updated at Posted at 2021-02-10

はじめに

画像をたくさん集めたい場合、画像検索結果から画像のソースをスクレイピングして画像をダウンロードする、みたいな記事はいくつかありますが、今回はGoogleで画像検索をしたときの結果をその場でスクリーンショットして画像を集める処理を自動化することで、その目的を達成することにしてみます。つまり、Googleの画像検索結果ページに一度アクセスするだけのリクエストで済み、あとはそこにある画像をスクショしているだけという状態をブラウザの自動化ツールであるSeleniumを使って作り出します。

注意点としては、画面に表示されているものをスクショしているだけなので画像サイズ(ピクセル数)は200x200程度の場合が多いです。用途としては問題ないかもしれませんが、仕方ありません。

検索クエリによると思いますが、今回は3分無いぐらいで500枚程度の画像が保存されました

環境

  • python 3.6.5

実装

SeleniumのChromeドライバーを使用しました。使用しているクロームと同じバージョンのドライバーをダウンロードしています

まず、検索結果からすべての画像を表示できるブラウザの状態を作ります。

from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.action_chains import ActionChains

def driver_with_scroll(url):
    options = Options()
    options.add_argument('--headless')
    driver = webdriver.Chrome('./chromedriver', chrome_options=options)
    driver.get(url)

    height = driver.execute_script("return document.body.scrollHeight")
    n_times = 1000 # スクロールをする回数(余裕を持ってこの値)
    total_height = 0
  
    for i in range(2): # 1回目: もっと表示ボタンが出るまで, 2回目: もっと表示ボタンを押してから
        for j in range(1, n_times):
            total_height += height
            driver.execute_script("window.scrollTo(0, " + str(total_height) + ");")
        if i == 1: continue
        time.sleep(1) # ボタンが表示される間
        driver.find_elements_by_xpath('//input')[-1].click()    
    return driver


q = '白文鳥'
url = f'https://www.google.com/search?q={q}&tbm=isch'
driver = driver_with_scroll(url)

ここまでで、このSeleniumのドライバーはGoogle画像検索結果のスクロールをして、さらにもっと表示ボタンを押した検索結果をすべて表示している状態にあります。ここから、このブラウザに表示されている検索結果の画像をスクリーンショットで保存していきます

検索結果から見るに、だいたいどの画像もwidthかheightが180以上であるようなので、その条件で足切りします

スクリーンショット 2021-02-11 1.37.05.png


img_dir = './img/' # 適当に
for i, elem_obj in enumerate(driver.find_elements_by_xpath('//img')):
    min_size = 180
    if elem_obj.size['height'] < min_size or elem_obj.size['width'] < min_size: continue
    fname = f'{img_dir}{q}_{i}.png'
    try:
        elem_obj.screenshot(fname)
    except:
        continue
driver.close() 

結果的に実行時間3分弱で500枚以上の画像が集まりました

スクリーンショット 2021-02-11 1.39.26.png

おわりに

  • メリット

    • imgタグであることと、widthかheightの指定のみに依存して画像を集めている
    • 各画像のsourceに対してrequestを送る必要がない
  • デメリット

    • 画像が小さい
    • スクリーンショットを実際にブラウザが動かす挙動をするので(headlessであっても)時間がかかる
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?