Pink Rose Flower

Python/Selenium

[selenium]윈도우에서 selenium이용해 구글 이미지 크롤링하기

hyunjoo 2022. 1. 4. 04:11

윈도우에서 selenium을 이용한 이미지 크롤링 실습을 해보자.

 

먼저, 파이썬에 가상 환경을 만들어 실행해 보자.

파이썬  venv 모듈을 이용하여 가상 환경을 만들어 준다.

 

venv — 가상 환경 생성 — Python 3.10.1 문서

 

venv — 가상 환경 생성 — Python 3.10.1 문서

venv — 가상 환경 생성 소스 코드: Lib/venv/ venv 모듈은 자체 사이트 디렉터리를 갖는 경량 《가상 환경》을 만들고, 선택적으로 시스템 사이트 디렉터리에서 격리할 수 있도록 지원합니다. 각 가

docs.python.org

위 사이트에 들어가면 venv 가상 환경을 만드는 명령어가 소개되어 있다.

 

일단 아래 명령어를 사용하여 가상환경을 만들어 주었다.

자신이 설치한 python 버전에 따라 (예: python3 - m venv selenium) 명령어를 변형시켜주면 된다.

그리고 venv 뒤에는 가상 환경의 이름을 설정해주는 것으로 자신이 원하는 이름을 설정해도 된다.

 

python -m venv selenium

 

위 명령어를 입력하면 selenium이라는 가상 환경이 생긴 것을 확인할 수 있다.

 

가상 환경 사용을 위해 selenium에서 Scripts 폴더로 이동한다.

 

cd selenium\Scripts

 

그리고 다음 명령어 activate 또는 .\activate 를 입력하여 가상 환경을 실행시킨다.

 

위와 같은 오류가 뜨는데 오류 해결은 아래 링크를 참고했다.

 

[PowerShell] VSCode 터미널 오류 : 이 시스템에서 스크립트를 실행할 수 없으므로 ~ .ps1 파일을 로드할 수 없습니다 (tistory.com)

 

[PowerShell] VSCode 터미널 오류 : 이 시스템에서 스크립트를 실행할 수 없으므로 ~ .ps1 파일을 로드할

VSCode 에서 npm을 설치하고 사용하고자 할 때 아래와 같은 어려움에 부딪칠 수 있다. 이는 스크립트 실행 권한이 제한되어 있는 상태이기 때문이다. 스크립트 실행 권한을 변경하기 위해서는 Window

singa-korean.tistory.com

위에 자료를 참고하여 오류를 해결해 준 후에,

activate 명령어로 실행되지 않는 다면 .\activate 명령어를 입력해준다.

그럼 위에 (selenium)이라는 표시가 생기면서 selenium이라는 가상 환경에 들어와 있다는 것을 알 수 있다.

다음 명령어를 입력하여 selenium을 설치해준다.

 

pip install selenium

 

selenium  공식 페이지에 들어가면 참고할 수 있는 코드가 있다. 이를 가져와 필요에 따라 코드를 수정해가며 실행하면 된다.

 

2. Getting Started — Selenium Python Bindings 2 documentation (selenium-python.readthedocs.io)

 

2. Getting Started — Selenium Python Bindings 2 documentation

2.2. Example Explained The selenium.webdriver module provides all the WebDriver implementations. Currently supported WebDriver implementations are Firefox, Chrome, IE and Remote. The Keys class provide keys in the keyboard like RETURN, F1, ALT etc. from se

selenium-python.readthedocs.io

from selenium import webdriver #셀레니엄 관련 라이브러리를 가져오는 코드
from selenium.webdriver.common.keys import Keys

driver = webdriver.Firefox() #크롬 드러아버를 열기
driver.get("http://www.python.org") #크롬드랑버로 구글로 이동

assert "Python" in driver.title
elem = driver.find_element_by_name("q")
elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
driver.close()

 

위와 같은 코드를 가져왔고 실행해보며 수정해보자.

 

먼저 구글 이미지 창을 열기 위해 아래와 같이 코드를 수정한다.

 

from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://www.google.co.kr/imghp?hl=ko&ogbl")

 

터미널 창에서 아래와 같은 명령어를 입력하거나 오른쪽 상단에 실행 버튼을 눌러 실행시킨다.

 

 

자동으로 구글 이미지 창이 열린다.

이제 입력 바에 '운동화'를 입력하고 enter입력까지 해보자.

 

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

driver = webdriver.Chrome()
driver.get("https://www.google.co.kr/imghp?hl=ko&ogbl")
elem = driver.find_element_by_name("q")
elem.send_keys("운동화") #키보드 입력값 설정
elem.send_keys(Keys.RETURN)

 

위에 코드를 입력 후 실행하면 아래와 같이 운동화를 검색한 결과를 볼 수 있다.

 

 

사진을 선택할 수 있는 코드를 작성해보자.

작은 이미지의 위치를 알기 위해 검사 버튼을 눌러 css요소의 class 값을 이용하여 선택해준다.

 

 

코드는 아래와 같다.

 

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

driver = webdriver.Chrome()
driver.get("https://www.google.co.kr/imghp?hl=ko&ogbl")
elem = driver.find_element_by_name("q")
elem.send_keys("운동화") #키보드 입력값 설정
elem.send_keys(Keys.RETURN)
driver.find_element_by_css_selector(".rg_i.Q4LuWd").click()

 

실행 결과, 첫 번째 운동화 사진을 선택하고 옆에 사진을 확대한 창이 뜬다.

 

 

이미지를 다운로드할 때는 큰 그림의 주소를 이용한다.

이미지의 주소를 불러오는 코드는 아래와 같다. 큰 이미지의 위치는 css요소로 불러오고 그 안에 담긴 사진의 주소를 받는다. 주소가 담긴 코드를 마지막에 출력해보자.

 

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

driver = webdriver.Chrome()
driver.get("https://www.google.co.kr/imghp?hl=ko&ogbl")
elem = driver.find_element_by_name("q")
elem.send_keys("운동화") #키보드 입력값 설정
elem.send_keys(Keys.RETURN)
driver.find_element_by_css_selector(".rg_i.Q4LuWd").click()
print(driver.find_element_by_css_selector('n3VNCb').get_attribute("scr"))

 

이 코드를 실행할 시 중간에 멈추는 오류가 발생하는데 이유는 이미지를 클릭하고 주소를 불러오는 과정에서 브라우저도 시간이 필요하기 때문이다. 그렇기 때문에 클릭하고 기다리는 시간을 지연시켜주는 코드를 추가해야 한다.

 

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


driver = webdriver.Chrome()
driver.get("https://www.google.co.kr/imghp?hl=ko&ogbl")
elem = driver.find_element_by_name("q")
elem.send_keys("운동화") #키보드 입력값 설정
elem.send_keys(Keys.RETURN)
driver.find_element_by_css_selector(".rg_i.Q4LuWd").click()
time.sleep(3)
print(driver.find_element_by_css_selector('.n3VNCb').get_attribute("src"))

 

위 코드 실행 시, 브라우저도 자동으로 열리고 터미널 창에 주소를 출력한 것을 확인할 수 있다.

 

 

이제 이 이미지 주소를 다운로드하는 코드를 만들어 보자.

이미지 주소를 imgUrl이라는 변수에 저장하고 이미지를 다운로드하는 코드인 urllib.request.urlretrieve(a,b)로 전달해준다.

a 에는 이미지 주소를 전달하고 b 에는 저장할 이미지의 이름을 지정해준다.

 

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import urllib.request

driver = webdriver.Chrome()
driver.get("https://www.google.co.kr/imghp?hl=ko&ogbl")
elem = driver.find_element_by_name("q")
elem.send_keys("운동화") #키보드 입력값 설정
elem.send_keys(Keys.RETURN)
driver.find_element_by_css_selector(".rg_i.Q4LuWd").click()
time.sleep(3)
imgUrl=driver.find_element_by_css_selector('.n3VNCb').get_attribute("src")
urllib.request.urlretrieve(imgUrl,"test.jpg")

 

실행하면 사진이 다운된 것을 확인할 수 있다.

 

 

이제는 구글에 운동화를 검색했을 때 나오는 모든 이미지를 다운로드할 수 있는 코드를 만들어보자.

 

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import urllib.request

driver = webdriver.Chrome()
driver.get("https://www.google.co.kr/imghp?hl=ko&ogbl")
elem = driver.find_element_by_name("q")
elem.send_keys("운동화") 
elem.send_keys(Keys.RETURN)
images=driver.find_elements_by_css_selector(".rg_i.Q4LuWd")
count=1
for image in images:
    image.click()
    time.sleep(3)
    imgUrl=driver.find_element_by_css_selector('.n3VNCb').get_attribute("src")
    urllib.request.urlretrieve(imgUrl,str(count)+".jpg")
    count+=1

 

위 코드를 실행하면 이미지가 다운로드하여지는데 46장에서 멈춘다. 

 

 

구글 이미지 창에서 스크롤을 내려야 이미지를 더 불러올 수 있는데 스크롤을 내려줄 코드가 없기 때문이다.

그리고 스크롤을 최대로 내리면 '결과 더 보기' 버튼을 눌러야 더 많은 사진을 불러올 수 있다.

 

 

그래서 스크롤을 모두 내리고 결과 더보기를 눌러 마지막 사진까지 저장할 수 있는 코드를 만들어 보자.

코드를 설명하면 스크롤을 끝까지 내렸을 때의 높이는 구해 last_height 변수에 저장한다.

그리고 스크롤을 내려가며 현재 스크롤 내린 곳까지의 높이를 계속해서 new_height에 업데이트해 저장해준다.

이렇게 last_height와 new_height 값을 비교해 가며 두 변수의 길이가 같아질 때까지 무한 루프를 이용하여 계속해서 스크롤을 내리는 작업을 한다. 그리고 더 보기 버튼이 나오면 누르는 코드도 무한 루프에 넣어주어 스크롤을 끝까지 내릴 수 있도록 한다. 버튼은 위에 동일하게 css 요소의 class 명을 사용하여 가져왔다.

마지막으로 두 길이가 같아지면 break를 걸어 무한 루프 문을 나오고 마지막 이미지까지 저장이 가능해진다.

 

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import urllib.request

driver = webdriver.Chrome()
driver.get("https://www.google.co.kr/imghp?hl=ko&ogbl")
elem = driver.find_element_by_name("q")
elem.send_keys("운동화") 
elem.send_keys(Keys.RETURN)

SCROLL_PAUSE_TIME = 1  

# Get scroll height
last_height = driver.execute_script("return document.body.scrollHeight") 

while True:
    # Scroll down to bottom
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

    # Wait to load page
    time.sleep(SCROLL_PAUSE_TIME)

    # Calculate new scroll height and compare with last scroll height
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        driver.find_element_by_css_selector('.mye4qd').click()
    last_height = new_height


images=driver.find_elements_by_css_selector(".rg_i.Q4LuWd")
count=1
for image in images:
    image.click()
    time.sleep(3)
    imgUrl=driver.find_element_by_css_selector('.n3VNCb').get_attribute("src")
    urllib.request.urlretrieve(imgUrl,str(count)+".jpg")
    count+=1

 

위 코드를 실행하게 되면 중간에 자동화 창이 종료가 되는데 이유는 더 보기 버튼이 나오지 않는 맨 마지막까지 내려가면 누를 버튼이 없기 때문이다.

 

그래서 이 버튼이 없어 오류가 날 때 무한 루프 문을 빠져나올 수 있도록 코드를 수정해 보자.

 

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import urllib.request

driver = webdriver.Chrome()
driver.get("https://www.google.co.kr/imghp?hl=ko&ogbl")
elem = driver.find_element_by_name("q")
elem.send_keys("운동화") 
elem.send_keys(Keys.RETURN)

SCROLL_PAUSE_TIME = 1

# Get scroll height
last_height = driver.execute_script("return document.body.scrollHeight")

while True:
    # Scroll down to bottom
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

    # Wait to load page
    time.sleep(SCROLL_PAUSE_TIME)

    # Calculate new scroll height and compare with last scroll height
    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


images=driver.find_elements_by_css_selector(".rg_i.Q4LuWd")
count=1
for image in images:
    image.click()
    time.sleep(3)
    imgUrl=driver.find_element_by_css_selector('.n3VNCb').get_attribute("src")
    urllib.request.urlretrieve(imgUrl,str(count)+".jpg")
    count+=1

 

위 코드를 실행하다 보면 이미지를 다운로드하는 과정에서 오류가 나기도 하는데 이때 오류가 나는 것을 무시하고 다음 사진을 다운로드할 수 있도록 코드를 수정해보자.

 

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import urllib.request

driver = webdriver.Chrome()
driver.get("https://www.google.co.kr/imghp?hl=ko&ogbl")
elem = driver.find_element_by_name("q")
elem.send_keys("운동화") 
elem.send_keys(Keys.RETURN)

SCROLL_PAUSE_TIME = 1  

# Get scroll height
last_height = driver.execute_script("return document.body.scrollHeight")

while True:
    # Scroll down to bottom
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

    # Wait to load page
    time.sleep(SCROLL_PAUSE_TIME)

    # Calculate new scroll height and compare with last scroll height
    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


images=driver.find_elements_by_css_selector(".rg_i.Q4LuWd")
count=1
for image in images:
    try:
        image.click()
        time.sleep(3)
        imgUrl=driver.find_element_by_css_selector('.n3VNCb').get_attribute("src")
        urllib.request.urlretrieve(imgUrl,str(count)+".jpg")
        count+=1
    except:
        pass
        
driver.close()

 

위에서도 문제가 되는 점  발견..!

큰 이미지를 가져오기 위해 class 명을 사용했는데 이 클래스명은 큰 이미지만을 가져오는 class 명이 아니기 때문에 큰 이미지 외에 다른 작은 이미지들도 가져오게 된다.

그래서 큰 이미지만 불러올 수 있는 구체적인 요소를 찾기 위해 아래와 같이 css 요소 대신 full xpath 요소로 큰 이미지를 불러오도록 코드를 수정해 보자.

 

 

 

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import urllib.request

driver = webdriver.Chrome()
driver.get("https://www.google.co.kr/imghp?hl=ko&ogbl")
elem = driver.find_element_by_name("q")
elem.send_keys("운동화") 
elem.send_keys(Keys.RETURN)

SCROLL_PAUSE_TIME = 1 

# Get scroll height
last_height = driver.execute_script("return document.body.scrollHeight")

while True:
    # Scroll down to bottom
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

    # Wait to load page
    time.sleep(SCROLL_PAUSE_TIME)

    # Calculate new scroll height and compare with last scroll height
    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


images=driver.find_elements_by_css_selector(".rg_i.Q4LuWd")
count=1
for image in images:
    try:
        image.click()
        time.sleep(3)
        imgUrl=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[2]/div/a/img').get_attribute("src")
        urllib.request.urlretrieve(imgUrl,str(count)+".jpg")
        count+=1
    except:
        pass

driver.close()

 

이제 전체 코드가 완성되었고 실행을 해보면,

 

운동화라고 검색해서 나온 모든 이미지가 저장되는 것을 확인할 수 있다.

 

 

폴더에서도 다운된 이미지들을 확인할 수 있다.

 

 


참고자료

반응형