컴퓨터/Python

Python (19) - 구글 이미지를 크롤링 하는 방법 (Selenium)

달서비 2023. 8. 9. 23:53

HTML을 뽑아 이용하여 크롤링도 할 수 있지만 때로는 직접 브라우저를 사용할 때가 있습니다. 이번에는 직접 브라우저를 활용하여 구글 이미지들을 크롤링하는 방법을 알아보겠습니다.

 

Selenium

Selenium 로고

먼저 크롤링은 웹상에서 수집된 정보를 수집해 오는 작업입니다. 그리고 Selenium은 프로그램을 이용하여 웹 자동화 및 테스트를 제공하는 프레임워크입니다. Selenium은 크롤링의 역할을 폭넓게 수행할 수 있습니다. 기존에 크롤러는 HTML 분석에 그쳤다면 직접 조작할 수 있습니다. 직접 조작할 수 있는 장점은 다음과 같습니다. 

  • 자바스크립트가 동적으로 만든 데이터를 크롤링할 수 있다.
  • HTML의 다양한 요소(input, button 태그 등)의 클릭 및 입력이 필요할 수 있다.

여담으로 Selenium은 다양한 언어로 제공합니다. 밑에는 해당 프레임워크 관련한 깃허브 링크를 남겼습니다.

https://github.com/SeleniumHQ/selenium

 

GitHub - SeleniumHQ/selenium: A browser automation framework and ecosystem.

A browser automation framework and ecosystem. Contribute to SeleniumHQ/selenium development by creating an account on GitHub.

github.com

 

사용하는 방법

1. Edge Web Driver를 다운로드합니다.

※ 윈도우에 내장된 edge 브라우저를 이용하여 진행하겠습니다.

Edge 브라우저 접속 - 설정 - Microsoft Edge 정보
해당 버전에 맞는 드라이버를 설치하면 된다

Edge 브라우저 - 설정 - Microsoft Edge 정보에서 버전을 확인한 아래 링크에서 버전에 맞는 드라이버를 설치합니다.

저 같은 경우는 108.0.1462.76 버전에 64비트를 다운로드하였습니다.

https://developer.microsoft.com/ko-KR/microsoft-edge/tools/webdriver/

 

Microsoft Edge WebDriver - Microsoft Edge Developer

beta Channel Preview channel for the next major version. Version: 109.0.1518.44: ARM64 | x64 | x86

developer.microsoft.com

 

2. 파이썬에도 selenium을 사용할 환경을 구축합니다.

pip install selenium

 

3. 드라이버의 경로를 설정 후 테스트 코드를 작동합니다.

from selenium import webdriver
driver = webdriver.Edge('./edgedriver/msedgedriver.exe')
url = 'https://www.google.com'
driver.get(url)

임의로 만든 소스 코드로 프로그램을 실행시킬 때 구글로 접속이 되면 성공입니다.

 

구글 이미지를 크롤링 하자.

소스 코드를 제작하기 전에 서비스 시나리오를 먼저 작성하겠습니다. 제가 작동하는 방식은 다음과 같습니다.

0. 이미지 다운로드를 받을 폴더를 설정한다. & init
1. Edge 브라우저에 접속 후 구글 이미지에 접속한다.
2. 구글 이미지 접속 후 원하는 검색어로 검색합니다.
2. 이미지가 전부 미리보기가 보일 때까지 밑으로 내린다.
3. 멈춘 경우 사진을 한 장씩 클릭한다
3-1. 확대된 이미지를 다운로드 한다
4. 사진 다운로드가 끝나면 완료 텍스트를 남기고 프로그램을 종료한다. 

※ Selenium 4.7.2 버전 및 파이썬 3.9 버전으로 진행했습니다. 버전에 따라 소스 코드가 실행될 수도 안될 수도, 있습니다.

※ 23.08.09 기준으로 작성하였으며 구글측에 업데이트에 따라 될수도 안될수도 있습니다.

 

0. 이미지 다운로드를 받을 폴더를 설정한다.

import os

#여기서 수정 가능한 변수들을 객체로 적어놓습니다.
class value(object):
    DRIVERADD = "C:/Users/hello/Desktop/RES_code/edgedriver/msedgedriver.exe" #사용자의 드라이버 위치를 추가합니다.
    SEARCH = "프로미스나인" #구글에 검색 키워드를 적습니다.
    COUNT = 100 #저장하고 싶은 사진의 숫자를 적어놓습니다.

#폴더 생성 (Step : 0)
def createDir(dir):
    try:
        if not os.path.exists(dir):
            os.makedirs(dir)
    except OSError:
        print("오류 : 폴더를 생성할 수 없습니다.")
Val = value()

dir = "./" + Val.SEARCH
createDir(dir)
print("진행 : 폴더생성을 완료하였습니다.")

createDir 함수는 폴더의 유무를 확인하고 폴더가 없는 경우 생성합니다. 해당 함수를 이용하여 폴더를 생성하도록 합니다. 또한 class를 만든 것이 있습니다. 저는 이것을 init으로 사용하였는데 여기서 자신이 필요로 하는 작업과 데이터의 갯수를 적으면 됩니다.

 

1. 구글 이미지에 접근 후 검색

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

#구글 검색창에서 검색하는 과정 (Step : 1)
driver = webdriver.Edge(Val.DRIVERADD) #크롬드라이버 장소
driver.get("https://www.google.co.kr/imghp?hl=ko&tab=wi&authuser=0&ogbl") #구글 이미지 검색
elem = driver.find_element(By.NAME, "q") #구글 검색창 선택
elem.send_keys("프로미스나인")
elem.send_keys(Keys.RETURN)
print("진행 : 구글에서 이미지검색을 완료하였습니다.")

Driver를 이용하여 구글 이미지 검색을 합니다. "NAME = 'q'" 는 input 태그로 해당 태그를 이용하여 이름을 입력합니다.

 

2. 아래 끝까지 창을 내리기

from selenium.webdriver.common.by import By

#검색 이후 사진을 다운로드하기 위해 스크롤 한다. (Step : 2)
last_height = driver.execute_script("return document.body.scrollHeight") # 브라우저의 높이
while 1:
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 브라우저 끝까지 스크롤을 내림
    time.sleep(1)
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        try:
            driver.find_element(By.CSS_SELECTOR, ".mye4qd").click()
        except:
            break
    last_height = new_height
print("진행 : 스크롤을 완료하였습니다.")

자바스크립트를 사용하여 아래 끝까지 창을 내립니다. window.scrollTo(x,y) 메소드는 x축, y축으로 스크롤 하는 역할을 합니다. 그리고 document.body.scrollHeight은 전체 높이를 출력하는 메소드 입니다. 구글은 이미지가 중간에 가는 경우 "결과 더보기" 기능입니다. 클릭할 수 있도록 구현하였습니다.

 

간단하게 진행 방법은 아래와 같습니다.

  1. 브라우저를 끝까지 내린다
  2. 끝까지 내린 경우 "결과 더 보기"를 이용하여 마저 검색한다
  3. 브라우저를 끝까지 내린다.
  4. 완료되었으면 멈춘다.

 

3. 이미지 클릭 및 다운로드 하기

#크롤링 실행 (Step : 3)
count = 1
imgs = driver.find_elements(By.CSS_SELECTOR, ".rg_i.Q4LuWd")
for img in imgs:
    try:
        img.click()
        time.sleep(2)
        imgUrl = driver.find_element(By.XPATH,'//*[@id="Sva75c"]/div[2]/div[2]/div[2]/div[2]/c-wiz/div/div/div/div[3]/div[1]/a/img[1]').get_attribute('src')

        opener = urllib.request.build_opener()
        opener.addheaders = [
            ('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1941.0 Safari/537.36')
        ]
        urllib.request.install_opener(opener)
        urllib.request.urlretrieve(imgUrl, dir + '/' + Val.SEARCH + str(count) + '.jpg')
        print(str(count) + "/" + str(Val.COUNT) + "다운로드가 완료되었습니다.")
        if count >= Val.COUNT:
            break
        count = count + 1
    except Exception as e:
        print('e : ', e)
        pass

이제 본격적으로 크롤링을 진행하려고 합니다. CSS_SELECTOR를 이용할 수도 있지만 인터넷에 많이 나와있는 방법인 XPATH를 이용하여 구현해보았습니다. XPATH가 달라서 안되는 경우가 있는데 그런경우에 F12번을 눌뤄 가지고 오려고하는 이미지에 XPATH를 복사해서 넣으면 됩니다.

 

  1. 이미지를 클릭한다
  2. XPATH의 값 데이터와 opener 권한을 받는다.
  3. 다운로드
  4. 자신이 다운로드 하려고 하는지 확인 ,없는 경우에는 이하 반복

 

 

4. 사진 다운로드가 끝나면 완료 텍스트를 남기고 프로그램을 종료한다. 

#완료 (Step : 4)
driver.close()
print("완료 : 추출이 완료되었습니다")

driver.close() 메소드는 실행한 edge 브라우저를 종료합니다. 브라우저 종료로 시스템을 마무리하도록 합니다.

 

전체 소스코드

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import time
import urllib.request
import os

#여기서 수정 가능한 변수들을 객체로 적어놓습니다.
class value(object):
    DRIVERADD = "C:/Users/hello/Desktop/RES_code/edgedriver/msedgedriver.exe" #사용자의 드라이버 위치를 추가합니다.
    SEARCH = "프로미스나인" #구글에 검색 키워드를 적습니다.
    COUNT = 100 #저장하고 싶은 사진의 숫자를 적어놓습니다.

def createDir(dir):
    try:
        if not os.path.exists(dir):
            os.makedirs(dir)
    except OSError:
        print("오류 : 폴더를 생성할 수 없습니다.")
Val = value()


#폴더 생성 (Step : 0)
dir = "./" + Val.SEARCH
createDir(dir)
print("진행 : 폴더생성을 완료하였습니다.")

#구글 검색창에서 검색하는 과정 (Step : 1)
driver = webdriver.Edge(Val.DRIVERADD) #크롬드라이버 장소
driver.get("https://www.google.co.kr/imghp?hl=ko&tab=wi&authuser=0&ogbl") #구글 이미지 검색
elem = driver.find_element(By.NAME, "q") #구글 검색창 선택
elem.send_keys(Val.SEARCH)
elem.send_keys(Keys.RETURN)
print("진행 : 구글에서 이미지검색을 완료하였습니다.")

#검색이후 사진을 다운로드하기위해 스크롤 한다. (Step : 2)
last_height = driver.execute_script("return document.body.scrollHeight") # 브라우저의 높이
while 1:
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 브라우저 끝까지 스크롤을 내림
    time.sleep(1)
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        try:
            driver.find_element(By.CSS_SELECTOR, ".mye4qd").click()
        except:
            break
    last_height = new_height
print("진행 : 스크롤을 완료하였습니다.")

#크롤링 실행 (Step : 3)
count = 1
imgs = driver.find_elements(By.CSS_SELECTOR, ".rg_i.Q4LuWd")
for img in imgs:
    try:
        img.click()
        time.sleep(2)
        imgUrl = driver.find_element(By.XPATH,'//*[@id="Sva75c"]/div[2]/div[2]/div[2]/div[2]/c-wiz/div/div/div/div[3]/div[1]/a/img[1]').get_attribute('src')

        opener = urllib.request.build_opener()
        opener.addheaders = [
            ('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1941.0 Safari/537.36')
        ]
        urllib.request.install_opener(opener)
        urllib.request.urlretrieve(imgUrl, dir + '/' + Val.SEARCH + str(count) + '.jpg')
        print(str(count) + "/" + str(Val.COUNT) + "다운로드가 완료되었습니다.")
        if count >= Val.COUNT:
            break
        count = count + 1
    except Exception as e:
        print('e : ', e)
        pass

#완료 (Step : 4)
driver.close()
print("완료 : 추출이 완료되었습니다")