はじめに
画像をたくさん集めたい場合、画像検索結果から画像のソースをスクレイピングして画像をダウンロードする、みたいな記事はいくつかありますが、今回は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以上であるようなので、その条件で足切りします
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枚以上の画像が集まりました
おわりに
-
メリット
- imgタグであることと、widthかheightの指定のみに依存して画像を集めている
- 各画像のsourceに対してrequestを送る必要がない
-
デメリット
- 画像が小さい
- スクリーンショットを実際にブラウザが動かす挙動をするので(headlessであっても)時間がかかる