Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
1
Help us understand the problem. What is going on with this article?
@sentencebird

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

はじめに

画像をたくさん集めたい場合、画像検索結果から画像のソースをスクレイピングして画像をダウンロードする、みたいな記事はいくつかありますが、今回は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であっても)時間がかかる
1
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
1
Help us understand the problem. What is going on with this article?