요즘 구글의 Teachable Machine에 관심이 생겨서 여러 가지를 실험해보려고 했는데....
사진 모으는게 겁나 귀찮습니다
그래서 구글 이미지에서 자동으로 이미지를 다운로드해주는 프로그램을 만들었습니다.
원래는 적당한 게 있나 찾아보려고 했는데
다 옛날 거라 구글처럼 웹사이트가 자주 바뀌면 쓸 수가 없더라고요.(찾아본것중 절반이 클래스명이 다름)
사실 google-image-download라는 파이썬 모듈이 있습니다만 내친 김에 공부도 할 겸 직접 만들었습니다
알아야 하는 것들:
파이썬, 셀레니움, HTML
일단 코드는 다음과 같습니다:
from requests import get
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from time import sleep
import os
from tkinter import Tk
from tkinter.simpledialog import askstring
from shutil import copyfileobj
from base64 import b64decode
window = Tk()
# 유저가 입력한 키워드들을 리스트로 저장
keyword_list = askstring(
title='구글 이미지 다운로더', prompt='검색할 키워드를 콤마(,)로 구분해주세요(키워드가 두단어 이상이라면 공백으로 구분하세요').split(',')
window.destroy()
PATH = './chromedriver'
# 크롬을 띄우지 않는 옵션 설정
options = webdriver.ChromeOptions()
options.headless = True
try:
driver = webdriver.Chrome(PATH, options=options)
# 키워드 별로 반복문을 돌림
for keyword in keyword_list:
# 구글의 키워드 검색결과의 이미지 탭으로 가는 링크
url = '''https://www.google.com/search?tbm=isch&source=hp&biw=&bih=&ei=0VgdX4viLcq9hwOB7IngCQ&q=''' + keyword.strip()
driver.get(url)
# 폴더가 없으면 키워드로 폴더를 만듦
try:
parent_dir = "./images/"
path = os.path.join(parent_dir, keyword)
os.mkdir(path)
print('Path made for ' + keyword)
except:
print('Directory already exists for keyword:', keyword)
# 페이지가 로딩이 느릴 때를 대비해 5초를 기다림
sleep(5)
# 다음 페이지의 가장 밑까지 가게한다
last_height = driver.execute_script('return document.body.scrollHeight')
while True:
driver.execute_script(
'window.scrollTo(0,document.body.scrollHeight)')
sleep(1)
new_height = driver.execute_script(
'return document.body.scrollHeight')
if new_height == last_height:
# 이미지를 더 로딩하는 버튼을 누름
try:
driver.find_element_by_class_name('mye4qd').click()
sleep(1)
except:
break
last_height = new_height
print('Done scrolling')
# 페이지 내 모든 이미지를 찾음
image_urls = driver.find_elements_by_css_selector('img.rg_i.Q4LuWd')
print('Found', len(image_urls), 'results')
count = 1
for image_thumbnail in image_urls:
# 원본 이미지를 다운로드하기 위해 썸네일을 클릭함
ActionChains(driver).click(image_thumbnail).perform()
sleep(2)
# 같은 클래스를 가진 이미지가 여러개이기 때문에 xpath를 통해 지정함
image_url = driver.find_element_by_xpath(
'/html/body/div[2]/c-wiz/div[3]/div[2]/div[3]/div/div/div[3]/div[2]/c-wiz/div/div[1]/div[1]/div/div[2]/a/img').get_attribute("src")
with open(f'./images/{keyword}/{count}.jpg', 'wb') as image_file:
# 이미지가 base64로 인코딩된 텍스트일때
if image_url.startswith('data:image/jpeg;base64,'):
# 이미지 데이터를 디코딩해 저장한다(데이터를 해석해 저장)-23번째 인덱스부터 시작한다.
image_file.write(b64decode(image_url[23:]))
else: 이미지의 소스가 링크일때
# requests.get 함수를 사용해 링크에서 이미지(와 기타 등등)을 가져온다-stream은 안정성을 위해 추가
response = get(image_url, stream=True)
# 이미지 데이터를 열고있는 파일에 저장한다.
copyfileobj(response.raw, image_file)
# 버퍼를 없앤다
del response
count += 1
print('Done scrapping images')
finally:
# 브라우저를 닫고 더 이상의 셀레니움을 사용한 코드 실행을 멈춤
driver.quit()
수정사항:
찾는 이미지는 400개지만 실제 다운로드는 200~300인 것(수정됨)
해당 프로그램을 사용하려면 실행 후 가만히 놔두고 멈추기까지 기다려야 모든 결과를 얻을 수 있다.
해당 이미지의 원본을 긁어오는 것이 아닌 구글의 썸네일(?) 수준으로 가져오기에 화질이 좋지 않다.(300p 정도)(수정됨)
시작에 tkinter를 사용해 간단한 GUI를 만들었습니다.
Headless Chrome을 통해 크롬이 켜지지 않고 이미지를 다운로드할 수 있게 업데이트했습니다.
- tk 창 하나가 뜨는데 무시하고 다른 일 하시면 됩니다.
'프로젝트 > 파이썬' 카테고리의 다른 글
[파이썬] GCP를 이용한 유튜브 자막 프로그램 {K-UZA} (0) | 2021.04.29 |
---|---|
[파이썬] 네이버 날씨와 뉴스 자동화 - 이메일로 보내기 (0) | 2021.03.12 |