juuuding

Chapter 05 크롤링, 이미지처리, 데이터분석 시각화 프로그램 만들기 # 19 본문

Python/파이썬과 40개의 작품들

Chapter 05 크롤링, 이미지처리, 데이터분석 시각화 프로그램 만들기 # 19

jiuuu 2023. 2. 15. 15:55

 #19 구글 이미지 크롤링

 

* 사전 지식

 - 크롤링은 주피터 노트북 형식으로 파이썬 코드를 작성하고 테스트 하는 것이 좋다. 사이트들은 기계의 접속을 싫어하는데, 우리가 파이썬 파일로 반복하여 접속하면 기계가 접속했다고 판단하여 더이상 접속이 안될 수도 있기 때문이다. .py 형식으로 파이썬 코드를 만들고 크롤링을 진행하면 한번의 코드 실수로 인해 다시 접속해야한다. .ipynb 의 주피터 노트북 방식을 사용하면 접속하는 부분까지는 한 번 진행하고 접속해둔 상태에서 코드를 수정하며 웹상에서 데이터를 찾을 수 있다. 크롤링을 할 때 어떻게 사람이 접속한 것처럼 보이게 만드는지가 중요하다.

 

1. 라이브러리 설치

 selenuium : 웹을 제어하는 라이브러리

 webdriver-manager : 웹 드라이버를 사용하는 크롬 드라이버 파일을 쉽게 다운로드 할 수 있는 라이브러리

pip install selenium
pip install webdriver-manager

 

2. 크롬 드라이버를 자동으로 설치하기

# 구글 크롬 드라이버 자동 설치를 위한 라이브러리
from webdriver_manager.chrome import ChromeDriverManager
# 크롬 드라이버 제어를 위한 selenium 라이브러리
from selenium import webdriver

# 크롬 드라이버 시작
driver = webdriver.Chrome(ChromeDriverManager().install())

# 구글 이미지 검색 사이트로 이동
URL='https://www.google.co.kr/imghp'
driver.get(url=URL)

#사이트로 이동할 때까지 최대 10초 기다림
driver.implicitly_wait(time_to_wait=10)

- 구글 크롬 드라이버가 작동 되었고 구글의 이미지 검색 사이트로 접속하였다. 페이지 윗 부분에 "Chrome이 자동화된 테스트 소프트웨어에 의해 제어되고 있습니다"라는 문구가 나온다.

 

 

3. 구글 상에서 이미지 크롤링 하는 코드 만들기

  .ipynb 파일에서 <+코드>를 눌러 다음 코드를 작성한다. 앞서 쓴 코드는 컴퓨터의 메모리상에 남아 동작하고 있다. 

# 키 입력을 위한 라이브러리
from selenium.webdriver.common.keys import Keys
# CSS선택을 위한 라이브러리
from selenium.webdriver.common.by import By

elem = driver.find_element(By.CSS_SELECTOR,"body > div.L3eUgb > div.o3j99.ikrT4e.om7nvf > form > div:nth-child(1) > div.A8SBwf > div.RNNXgb > div > div.a4bIc > input")
# 바다를 입력 후 엔터키 눌러 검색
elem.send_keys("바다")
elem.send_keys(Keys.RETURN)

 

 크롬에서 css selector을 통해 값을 찾는 방법은 크롬에서 [F12] 키를 눌러 웹의 소스에서 찾고 싶은 부분의 소스코드를 마우스 커서 아이콘을 클릭하여 찾으면 된다. 

 

 찾은 검색창의 소스에 마우스 오른쪽을 클릭하여 [copy] -> [copy selector]로 복사한다. 그 값을 find_element에 넣으면 된다. 셀레니움에서는 selector을 이용하여 원소를 찾을 수 있다. 하나의 원소를 찾을 때는 find_element를 사용하고 여러개의 원소를 찾을 때는 find_elements를 사용한다. 복수의 의미로 s를 사용한다. 원소를 찾을 때 xPath, styles도 사용할 수 있다.

 

 

import time

# body 부분 찾기
elem = driver.find_element(By.TAG_NAME,"body")

#페이지 다운키 60회 눌러 사진 계속 보이게
for i in range(60):
    elem.send_keys(Keys.PAGE_DOWN)
    time.sleep(0.1)

try:
    #중간에 [결과더보기] 버튼이 있다면 눌러서 계속 보이게
    driver.find_element(By.CSS_SELECTOR,'#islmp > div > div > div > div > div.gBPM8 > div.qvfT1 > div.YstHxe > input').click()

    for i in range(60):
        elem.send_keys(Keys.PAGE_DOWN)
        time.sleep(0.1)
except:
    pass

  구글 이미지의 검색 사이트는 중간에 [결과더보기] 버튼을 눌러야 추가적으로 사진을 볼 수 있다. 위의 코드로 [결과더보기] 버튼을 눌러 많은 사진을 크롬 상에 출력했다.

 

 

links=[]

#이미지의 원소를 모두 찾기
images = driver.find_elements(By.CSS_SELECTOR,"#islrg > div.islrc > div > a.wXeWr.islib.nfEiy > div.bRMDJf.islir > img")

#찾은 이미지 수만큼 반복
for image in images:
    #이미지 링크 주소가 있다면 참
    if image.get_attribute('src') is not None:
        #이미지 다운로드 링크 주소를 links 리스트에 추가
        links.append(image.get_attribute('src'))

print(' 찾은 이미지 개수:', len(links))

 copy select를 사용하여 여러 사진의 원소 값을 찾은 결과 이러한 값들이 나왔다.

  #islrg > div.islrc > div:nth-child(2) > a.wXeWr.islib.nfEiy > div.bRMDJf.islir > img

  #islrg > div.islrc > div:nth-child(3) > a.wXeWr.islib.nfEiy > div.bRMDJf.islir > img

  #islrg > div.islrc > div:nth-child(7) > a.wXeWr.islib.nfEiy > div.bRMDJf.islir > img

이를 통해 여러 개의 사진을 모두 찾기 위해서 div:nth-child(2) -> div로 변경하면 모든 사진을 선택할 수 있게 된다.

  #islrg > div.islrc > div > a.wXeWr.islib.nfEiy > div.bRMDJf.islir > img

 

 

#사진을 다운로드 받기 위한 라이브러리
import urllib.request

#links의 리스트를 enumerate하여 반복. k는 번호, i는 links리스트의 원소값
for i, k in enumerate(links):
    url = k
    #사진 다운로드
    urllib.request.urlretrieve(url, "C:\\python_40\\19. Crawling google image\\download_pic"+str(i)+".jpg")

    print('다운로드 완료하였습니다.')

 사진들을 저장하고 싶은 경로를 지정하여 사진을 다운로드 했다. 이로써 구글 이미지에서 "바다"를 검색하면 나오는 모든 사진을 나의 폴더에 저장하였다. 

 

위의 .ipynb의 주피터 노트북으로 만든 파이썬 코드를 하나의 코드로 합쳐 .py 파일로 만들어서 실행하여도 동일한 결과를 얻을 수 있다. 크롤링으로 테스트를 할 때는 .ipynb로 진행하고 코드가 완성되면 .py 파일로 합쳐 실행하면 된다. 

 

 

 

4. 주피터 노트북을 py 코드로 변경

 해당 폴더(19. Crawling google image)에서 [통합 터미널 열기]를 하여 그 터미널에서 다음과 같이 명령어를 입력한다.

pip install nbconvert
jupyter nbconvert --to script main-19.ipynb

 * NotJSONError(("Notebook does not appear to be JSON: %r" % s)[:77] + "...") from e
nbformat.reader.NotJSONError: Notebook does not appear to be JSON: ''. 

 다음과 같은 오류가 뜨는데 아직 해결하지 못하였다.