공부방/Upstage AI Lab 4기

7/8 학습일지 | 파이썬 동적페이지 웹크롤링

Eddie_D 2024. 7. 8. 23:04
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time

service = Service(ChromeDriverManager().install())

driver = webdriver.Chrome(service=service)
driver.get("https://www.opinet.co.kr/searRgSelect.do")

지난 번에 크롬 드라이브를 깔고, 원하는 url을 가져오는 것까지 했다. 오피넷이라는 웸페이지에서 크롤링을 하려고 하는데, 이 웹페이지의 경우 우회해서 들어오는 걸 막고 있어서, url을 가져다 붙여도 자꾸 홈페이지 맨 처음 화면으로 들어가진다. 이 때에는 원하는 탭에서 자바스크립트 함수를 호출하고 있는 코드를 확인한다.

지역별
이 부분에서 goSubPage 가 자바스크립트의 함수 이름이고, 그 뒤 숫자는 인자들. 그래서 이 페이지로 바로 들어가고 싶다면, 아래 코드를 입력해주면 된다. 근데 중간에 time.sleep을 붙여줘야 하는데 이건 2초 정도 기다렸다가 실행하라는 뜻이다.

첫 화면이 완전히 로딩될때까지 2초 정도 기다렸다가, 다음인 '현 주유소 찾기' 페이지로 넘어가라는 의미. 그리고 driver.execute_script('goSubPage(0,0,99)')를 사용하여 자바스크립트 함수를 호출할 수 있다. (Selenium을 통해 특정 자바스크립트 함수를 직접 실행하는 방법)

time.sleep(2)
driver.execute_script('goSubPage(0,0,99)')

그 다음 각 지역에 따른 주유소 목록을 모두 뽑아내는 걸 할텐데, 먼저 목록을 가져오자!

이렇게 코드를 입력하면 된다고!!!(강의에서는 그랬는데!) 오류가 뜬다. find_element_by_xpath가 없다니!!! 해결방법은 챗지피티가 알려줬다. (진짜 챗지피티 최고다..)

Selenium의 `find_element_by_*` 메서드들은 Selenium 4에서 deprecated되었습니다. (Selenium 4 버전부터는
find_element_by_*메서드들이 더 이상 권장되지 않고, 향후 버전에서 제거될 예정이라는 뜻입니다. 현재 버전에서는 사용할 수 있지만, 최신 버전의 Selenium에서는 대신 새로운 방법을 사용하는 것이 좋습니다.) 대신, `find_element` 메서드를 사용하고 `By` 클래스를 사용하여 요소를 찾는 방식을 추천합니다.

해결 방법
1. `find_element` 메서드와 `By` 클래스를 사용: Selenium 4에서 요소를 찾는 새로운 방식입니다.
2.`selenium.webdriver.common.by.By` 클래스를 사용하여 XPath 지정: 이 클래스를 사용하여 요소를 찾습니다. 

from selenium.webdriver.common.by import By
sido = driver.find_element(By.XPATH, '//*[@id="SIDO_NM0"]') 을 추가해서 넣으니 잘 실행되었다. 시/도의 위치 태그를 sido에 저장해넣었고, sido를 실행해보면 WebElement로 표현되는 걸 볼 수 있다. 

time.sleep(2)
sido = driver.find_element(By.XPATH, '//*[@id="SIDO_NM0"]')
sido.find_elements(By.TAG_NAME, 'option')

그리고 옵션이라는 태그에 저장된 값들을 가져온다. 옵션값들을 sido_names 안으로 넣고, for문으로 돌려서 값을 sido_list에 넣은 뒤 빼내면 잘 나온다. (얏호!)

time.sleep(2)
sido = driver.find_element(By.XPATH, '//*[@id="SIDO_NM0"]')
sido_names = sido.find_elements(By.TAG_NAME, 'option')

sido_list= []
for sido_name in sido_names:
    sido_list.append(sido_name.get_attribute('Value'))

sido_list

결과값

['', '서울특별시', '부산광역시', '대구광역시', '인천광역시', '광주광역시', '대전광역시', '울산광역시', '세종특별자치시', '경기도', '강원특별자치도', '충청북도', '충청남도', '전북특별자치도', '전라남도', '경상북도', '경상남도', '제주특별자치도']

똑같은 방식으로 시/군/구에 대해서도 하고, 시/구와 시/군/구를 임의로 지정(sido.send_keys('서울특별시')) 한 뒤에 조회 버튼과 엑셀 저장 버튼을 찾아서 클릭하게 시킨다. (.click() 이렇게 괄호를 뒤에 붙여야 함!) 여기까지 코드를 정리해보면... 

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
import time

service = Service(ChromeDriverManager().install())

driver = webdriver.Chrome(service=service)
driver.get("https://www.opinet.co.kr/searRgSelect.do")
time.sleep(2)
driver.execute_script('goSubPage(0,0,99)')

time.sleep(2)
sido = driver.find_element(By.XPATH, '//*[@id="SIDO_NM0"]')
sido_names = sido.find_elements(By.TAG_NAME, 'option')

sido_list= []
for sido_name in sido_names:
    sido_list.append(sido_name.get_attribute('Value'))

sido_list = sido_list[1:]
sido.send_keys('부산광역시')

time.sleep(2)
sigungu = driver.find_element(By.XPATH, '//*[@id="SIGUNGU_NM0"]')
sigungu_names = sigungu.find_elements(By.TAG_NAME, 'option')

sigungu_list= []
for sigungu_name in sigungu_names:
    sigungu_list.append(sigungu_name.get_attribute('Value'))

sigungu_list = sigungu_list[1:]

sigungu.send_keys(['강서구'])

#조회 버튼
driver.find_element(By.XPATH, '//*[@id="searRgSelect"]').click()

#엑셀 저장 버튼
driver.find_element(By.XPATH, '//*[@id="templ_list0"]/div[7]/div/a').click()

지금까지 만든 코드는 '부산광역시', '강서구'를 누른 뒤에 조회 - 엑셀 저장을 누르는 것을 해준 것. 이제부터, 이걸 자동으로 서울부터 제주도까지 모든 시군구를 돌아가면서 자동으로 엑셀을 저장하는 코드로 바꿔줄 것이다. 아래는 완성된 코드! 중간에 time.sleep(2)가 빠지면 실행이 안되니, 잘 생각하면서 넣어줘야한다.

#webdriver를 키고 오피넷 지역별 주유소 찾기 탭으로 바로 접속
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
import time

service = Service(ChromeDriverManager().install())

driver = webdriver.Chrome(service=service)
driver.get("https://www.opinet.co.kr/searRgSelect.do")
time.sleep(2)
driver.execute_script('goSubPage(0,0,99)')

#시/도 목록 가져오기
time.sleep(2)
sido = driver.find_element(By.XPATH, '//*[@id="SIDO_NM0"]')
sido_names = sido.find_elements(By.TAG_NAME, 'option')

sido_list= []
for sido_name in sido_names:
    sido_list.append(sido_name.get_attribute('Value'))

sido_list = sido_list[1:]

#4원하는 지역으로 이동한다 
for sido_name in sido_list:
    sido = driver.find_element(By.XPATH, '//*[@id="SIDO_NM0"]')
    sido.send_keys(sido_name)
    time.sleep(2)

    #5시/군/구 목록 가져온다
    sigungu = driver.find_element(By.XPATH, '//*[@id="SIGUNGU_NM0"]')
    sigungu_names = sigungu.find_elements(By.TAG_NAME, 'option')

    sigungu_list= []
    for sigungu_name in sigungu_names:
        sigungu_list.append(sigungu_name.get_attribute('Value'))

    sigungu_list = sigungu_list[1:]
    
    #6목록으로 반복문을 수행하면서 조회, 엑셀 저장을 누른다 
    for sigungu_name in sigungu_list:
        sigungu = driver.find_element(By.XPATH, '//*[@id="SIGUNGU_NM0"]')
        time.sleep(2)
        sigungu.send_keys(sigungu_name)
        time.sleep(2)
        #조회 버튼
        driver.find_element(By.XPATH, '//*[@id="searRgSelect"]').click()
        time.sleep(2)
        #엑셀 저장 버튼
        driver.find_element(By.XPATH, '//*[@id="templ_list0"]/div[7]/div/a').click()

열심히 저장하다가 중간에 노트북이 잠자기 모드가 되어 끊겼다ㅠ