반응형

📝동적 크롤링

동적인 데이터를 수집하는 방법을 말한다.

동적인 데이터란 입력, 클릭, 로그인 등과 같이 페이지 이동이 있어야 보이는 데이터를 말한다.

정적크롤링 수집하는 속도가 느리다는 단점이 있지만 더 많은 정보를 수집할 수 있다는 장점

 

 

셀레니움이라는 것을 사용하여 동적 크롤링하겠습니다.

일단 Chrome으로 진행해주시고 Chromdriver라는게 필요합니다.

 

https://sites.google.com/chromium.org/driver/downloads

 

ChromeDriver - WebDriver for Chrome - Downloads

Current Releases If you are using Chrome version 92, please download ChromeDriver 92.0.4515.43 If you are using Chrome version 91, please download ChromeDriver 91.0.4472.101 If you are using Chrome version 90, please download ChromeDriver 90.0.4430.24 If y

sites.google.com

여기에서 다운 받아주세요 버전은 최신 버전으로 다운 받아주세요

 

내가 쓰는 Chrome 버전하고 호환이 되어야합니다. 따로 확인하는 법은 잘 모르겠고 밑에 코드 돌려서 에러 나오면 버전이 안 맞다고 하니까 그 버전으로 바꿔주시면 되겠습니다.

# 본 프로그램은 동적인 웹페이지를 크롤링하는 프로그램입니다.
# 작성 시작일 2021. 04. 16
# 수정일 2023.06.14 Selenimum Version 변경으로 인한 수정
# 작성자 이성재
# Selenium.py
# Python 3.11 Selenium 4.1.0, Chrom Version 114

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service as ChromeService
import time
import urllib.request

# 크롬 열고 검색하기
path = "C://chromedriver/chromedriver.exe" # 웹 드라이버가 있는 경로

options = webdriver.ChromeOptions()
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option("useAutomationExtension", False)
service = ChromeService(executable_path=path)
driver = webdriver.Chrome(service=service, options=options)

driver.get("https://www.google.co.kr/imghp?hl=ko") # 구글 이미지 메인 페이지
elem = driver.find_element(By.NAME, 'q') # driver.find_element_by_name("q") # 검색 부분에 name이 q이다
elem.send_keys("배우") # 검색하고자 하는 것
elem.send_keys(Keys.RETURN) # 엔터값 전송 크롤링이라는 글자를 입력하고 엔터를 누르는 과정


# 페이지 끝까지 스크롤 내리기
SCROLL_PAUSE_TIME = 1 # 대기시간을 1초로 셋팅

# 스크롤 깊이 측정하기 자바스크립트문을 실행시킴
last_height = driver.execute_script("return document.body.scrollHeight")

while True:
    # 스크롤 끝까지 내리기
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

    # 페이지 로딩 기다리기
    time.sleep(SCROLL_PAUSE_TIME)

    # 더 보기 요소가 있을 경우 클릭하기
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        try:
            driver.find_element(By.CSS_SELECTOR, '.mye4qd').click() # 더 보기에 css name이 mye4qd이다
        except:
            break
    last_height = new_height

# 이미지를 찾고 , 다운받기
image_path = "c:/actor/" # 이미지 저장될 경로 설정
images_list = driver.find_elements(By.CSS_SELECTOR, '.rg_i.Q4LuWd') # driver.find_elements_by_css_selector(".rg_i.Q4LuWd")
# class 명이 rg_i Q4LuWd 이지만 .으로 구분하고 css가 2개 적용된 거임 # images_list는 배열이다 즉 여러개 이미지의 정보를 넣는다

count = 1

for image in images_list:

    try :
        image.click() # 크롬 브라우저에서 작은 이미지를 클릭하는 효과와 동일
        time.sleep(2) # 2초 기다린다.


        # f12을 사용하여 개발자모드에서 검사-> copy -> Copy Xpath를 해서 경로를 가지고 온다
        imgUrl = driver.find_element(By.XPATH,"//*[@id=\"Sva75c\"]/div[2]/div/div[2]/div[2]/div[2]/c-wiz/div/div/div/div[3]/div[1]/a/img").get_attribute("src")

        # "" 안에 " 기호를 쓰기위해 \ 로 감싸준다

        # 이미지를 urllib.request를 사용하여 저장
        # xpath 값 ,  저장될 공간 + 크롤링(이름)
        urllib.request.urlretrieve(imgUrl, image_path+"actor" + str(count) + ".jpg")

        count = count + 1

    except Exception as e:
        print("이미지를 저장할 수 없습니다.")
        print(e)
        pass # 에러 발생시 무시하고 계속 진행

# 프로그램 종료
driver.close()

 

  • path = "chromedriver/chromedriver.exe"
    • 다운 받은 chromdriver 있는 경로를 설정해주세요 저는 이 .py있는 곳에 chromedriver라는 폴더에 넣어놨습니다.
  • driver = webdriver.Chrome(path)
    • 경로에 있는 chrome driver를 로드합니다

 

  • elem = driver.find_element_by_name("q")
    • name = "q"라고 되어있는 검색 부분을 가져옵니다.
  • elem.send_keys("배우")
    • send_keys를 통해 driver가 "배우"라는 검색어를 입력하게 합니다.
  • elem.send_keys(Keys.RETURN)
    • Keys.RETURN이라고 넣어주면 엔터를 누르는 과정입니다.
  • SCROLL_PAUSE_TIME = 1
    • 스크롤 Pause 시간
  • last_height = driver.execute_script("return document.body.scrollHeight")
    • chromedriver한테 return document.body.scrollHeight 이러한 스크립트문을 하라고 명령합니다
    • 스크롤바가 있을 때 그 깊이를 측정하는 과정입니다.
  • driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    • 검색시 처음 나오는 화면이 0이고 document.body.scrollHeight(맨 밑)까지 스크롤바를 내리게 합니다.
  • time.sleep(SCROLL_PAUSE_TIME)
    • 대기시간을 1초를 주는 과정입니다.

 

코드는 엄청 빨리실행되는데 반해 검색해서 가려진 이미지들이 다 뜨는데 시간차이가 있기 때문에 그렇습니다.

 

# 더 보기 요소가 있을 경우 클릭하기
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        try:
            driver.find_element(By.CSS_SELECTOR, '.mye4qd').click() # 더 보기에 css name이 mye4qd이다
        except:
            break
    last_height = new_height

new_height에 다시 깊이를 잽니다 밑에 사진의 결과 더보기가 나올때까지 내려가야합니다.

 

 

📝동작과정 요약

  1. 먼저 현재 보이는 부분 깊이를 잽니다(last_height)
  2. 스크롤을 내립니다 (스크롤을 다 내리면 결과 더보기가 먼저 나오지 않고 로딩하면서 좀 더 사진이 나옵니다.)
  3. 거기에 보이는 부분 깊이를 잽니다 (new_height)
  4. new_height랑 last_height값은 다릅니다. 그 후 last_height에 new_height값을 넣어줍니다
  5. new_height는 끝에 도달하지 않는 이상 계속 갱신되니까 if문에 들어가지 않습니다.
  6. new_height 값과 last_height값이 같아진다는 거는 결과 더보기까지 내려갔다는 소리이니까 결과더보기에 해당하는 mye4qd라는 클래스를 가진 버튼을 클릭하게 합니다.

 

 

 

결과 더보기에 대한 class명입니다.

 

  • images_list = driver.find_elements_by_css_selector(".rg_i.Q4LuWd")
    • 이미지에 대한 요소를 저장하는 리스트를 만들어 넣습니다.
    • 사진 class명을 보면 rg_i랑 Q4LuWd라는 클래스를 가집니다.

 

  • image.click()
    • 이미지를 클릭

 

📝Xpath

Xpath는 마크업 언어에서 특정 요소를 찾기 위한 경로(path)를 나타내는 언어입니다. 여기에선 이미지의 실질적 경로를 의미하죠

 

클릭했을때 나오는 사진을 검사를 눌러 나오는 태그오른쪽 클릭 후  Copy - Copy Xpath를 합시다.

 

driver.find_elements_by_xpath로 Xpath값을 넣습니다.

그냥 붙혀넣으면 빨간줄이 생기는데 왜 생기냐면 더블쿼테이션 안에 더블 쿼테이션이 들어가서 그렇습니다.

"를 그냥 문자로 인식하게 하려면 \" 이렇게 쓰면 됩니다 \"가 그냥 " 문자로 표현한다고 생각하면 됩니다.

 

 

실행시키면 C드라이브 actor라는 폴더에 이미지가 저장이 됩니다.

 

반응형