LoginSignup
8
9

More than 5 years have passed since last update.

Google APIを使わずにGoogle画像検索で画像収集

Last updated at Posted at 2018-10-21

やりたいこと

PythonでGoogle APIを使わずにGoogle画像検索で好きな画像を収集したい!

Google APIを使わずにスクレイピングするメリット

  • 画像を集めている様子が視覚化されている。
  • 制限がAPIを利用するよりも少ない
    • Google APIは1キーワード当たり最大100枚。101枚目以降はエラーになる ・大量のワードを収集する際は有料  1,000query単位で$5

必要なもの

・Python 3
・Firefox(または他のブラウザ)
・Selenium
※seleniumをインストールしていない人は、コマンドプロンプトに次を入力してインストール
pip install selenium
・WebDriver(Firefox)
※下のリンクからOSに対応したWebDriverをダウンロードしてください!
https://github.com/mozilla/geckodriver/releases

サンプルコード

とりあえず動かしたいという方は、私が今回の記事を書く際に参考にさせてもらったフランスのランバートさんのGitHubに飛んで、完全なコードを入手してください。
ランバートさんのGitHub

では、説明を始めます!
使用するライブラリはこんな感じ↓

google-image-scraping.py
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import os
import json
import urllib
import sys
import time
geckodriverへのパスをOS環境変数に追加する
os.environ["PATH"] += os.pathsep + os.getcwd()

特にここはいじるとこはないと思いますので次!

google-image-scraping.py
# ファイル名
download_path = "動物画像/"
# 画像検索
words_to_search = ['ねこ','犬', 'うさぎ']
nb_to_download = [3,6,9]
first_image_position = [0,3,6]

フォルダ名の指定
download_path = "動物画像/"
検索するワードの指定
words_to_search = ['ねこ','犬', 'うさぎ']
保存する画像の枚数を指定
nb_to_download = [3,0,0]
保存を何枚目から始めるか指定
first_image_position = [5,0,0]

フォルダ名を変更したい、検索対象を変更したいなどのことがあれば、上記の部分を変更するだけで大丈夫です。
これに下記のコードを繋げれば、Google APIを使わずに画像を収集することができるようになります!

google-image-scraping.py
def main():
    if len(words_to_search) != len(nb_to_download) or len(nb_to_download) != len(first_image_position) :
        raise ValueError('You may have forgotten to configure one of the lists (length is different)')
    i= 0
    # For each word in the list, we download the number of images requested
    while i<len(words_to_search):
        print("Words "+str(i)+" : "+str(nb_to_download[i])+"x\""+words_to_search[i]+"\"")
        if nb_to_download[i] > 0:
            search_and_save(words_to_search[i],nb_to_download[i], first_image_position[i])
        i+=1


def search_and_save(text, number, first_position):
    # Number_of_scrolls * 400 images will be opened in the browser
    number_of_scrolls = int((number + first_position)/ 400 + 1) 
    print("Search : "+text+" ; number : "+str(number)+"; first_position : "+str(first_position)+" ; scrolls : "+str(number_of_scrolls))

    # Create directories to save images
    if not os.path.exists(download_path + text.replace(" ", "_")):
        os.makedirs(download_path + text.replace(" ", "_"))

    # Connect to Google Image
    url = "https://www.google.co.in/search?q="+text+"&source=lnms&tbm=isch"
    driver = webdriver.Firefox()
    driver.get(url)
    headers = {}
    headers['User-Agent'] = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"
    extensions = {"jpg", "jpeg", "png", "gif"}

    img_count = 0
    downloaded_img_count = 0
    img_skip = 0

    # Prepare Google Page
    for _ in range(number_of_scrolls):
        for __ in range(10):
            # Multiple scrolls needed to show all 400 images
            driver.execute_script("window.scrollBy(0, 1000000)")
            time.sleep(0.2)
        # to load next 400 images
        time.sleep(2.5)
        try:
            driver.find_element_by_xpath("//input[@value='Show more results']").click()
            time.sleep(2.5)
        except Exception as e:
            print("Less images found:"+ str(e))
            break

    # Process (download) images
    imges = driver.find_elements_by_xpath('//div[contains(@class,"rg_meta")]')
    print("Total images:"+ str(len(imges)) + "\n")
    for img in imges:
        if img_skip < first_position:
            # Skip first images if asked to
            img_skip += 1
        else :
            # Get image
            img_count += 1
            img_url = json.loads(img.get_attribute('innerHTML'))["ou"]
            img_type = json.loads(img.get_attribute('innerHTML'))["ity"]
            print("Downloading image "+ str(img_count) + ": "+ img_url)
            try:
                if img_type not in extensions:
                    img_type = "jpg"
                # Download image and save it
                req = urllib.request.Request(img_url, headers=headers)
                raw_img = urllib.request.urlopen(req).read()
                f = open(download_path+text.replace(" ", "_")+"/"+str(img_skip+downloaded_img_count)+"."+img_type, "wb")
                f.write(raw_img)
                f.close
                downloaded_img_count += 1
            except Exception as e:
                print("Download failed:"+ str(e))
            finally:
                print("")
            if downloaded_img_count >= number:
                break

    print("Total skipped : "+str(img_skip)+"; Total downloaded : "+ str(downloaded_img_count)+ "/"+ str(img_count))
    driver.quit()

if __name__ == "__main__":
    main()

上記のコードについても詳しく知りたいという方は、ランバートさんが細かく記事を作成しているのでそちらを参考にしてみてください!
ランバートさんのブログ

8
9
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
8
9