본문 바로가기
프로젝트

[selenium] 웹 크롤링으로 장소와 주소 긁어서 엑셀로 저장하기

by 포 키 2023. 11. 2.
728x90
반응형

오늘은 파이널 프로젝트에서 마케팅 부분으로 필요한 지도 시각화를 구현하기 위해 크롤링을 먼저 진행했다.

하나하나 복사해서 붙여와도 되는 정도였지만, 프로젝트라는것 자체가 수작업보다는 내 역량을 끌어올리기 위해

안되는 것도 되게 바꿔보는 시간을 갖는 것이라고 생각한다.

 

처음엔 셀레니움을 사용할 생각을 못하고 gpt에 조언을 구했었다.

그러다가 수업시간에 셀레니움을 배웠던 게 기억이 나서 셀레니움으로 시도해봤다.

다른 부분의 코드는 정보를 구하기 쉬웠지만 크게 두가지가 어려웠다.

그래서 오늘은 코드자체는 간결하기 때문에 어떤점이 힘들었는지를 먼저 작성하려한다.

 

 

문제점

1-1. 드라이브 연결문제

셀레니움의 크롬 드라이브를 사용했다.

위에서 path 설정이 완료된 상태였는데도 자꾸 드라이브쪽에서 문제가 생겼다.

TypeError: WebDriver.__init__() got an unexpected keyword argument 'executable_path'

 

결론은 gpt 에서 얻은 코드를 사용하지 않아서 해결되었다!

driver = webdriver.Chrome(executable_path='/path/to/chromedriver')

위의 코드가 gpt에서 준 코드인데 코드 자체적으로는 문제가 없지만, 나는 이미 위에서 지정했기 때문에 발생한 문제같다.

 

반복문때문에 gpt에 코드 조언을 구했는데 그러면서 크롬 드라이브의 버전 호환성 문제가 생겨버렸다.

똑같은 코드를 다른방식으로 해서 두번 작성해서 벌어진 일이어서 삭제해주고 끝났다!

 

 

1-2. 드라이브 종료문제

이건 쉬웠다.

내가 아무생각없이 코드 마지막에 드라이브 종료 코드를 삽입해서 생긴 문제였다.

SessionNotCreatedException: Message: session not created: Chrome failed to start: exited normally. (session not created: DevToolsActivePort file doesn't exist) (The process started from chrome location /root/.cache/selenium/chrome/linux64/119.0.6045.105/chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.)

 

다시 드라이브를 연결해주면 해결된다!!

 

 

2. 패스 찾아서 긁어오기

가장 중요한 문제점이었다.

셀레니움을 배우긴했어도 당시엔 <head>에서 <title>만을 추출해본게 다였으니.. 제대로 할 줄 몰랐던게 화근이었다.

오늘 내가 필요한 부분은 <body>에서 추출해와야 했는데, 그 안에서도 패스가 꽤 복잡한 상태였다.

/html/body/div/div[2]/div/div[3]/a[1]/p
<p class="title ellip">서울시민대학 동남권캠퍼스</p>

위의 패스에서 서울시민대학 동남권캠퍼스를 추출해내는 과정이 1차적으로 필요했다.

 

/html/body/div[1]/div[2]/div/div[3]/a[n]/ul/li[1]
<li class="ellip">서울특별시 은평구 통일로89길 12-6 (갈현동)</li>

다음으론 서울특별시 은평구 통일로89길 12-6 (갈현동)의 주소부분을 추출해내는 과정이 2차적으로 필요했다.

 

그래서 페이지 검사를 통해 패스를 찾는 것은 쉬웠지만, 막상 코드 부분을 어떻게 수정해야할지가 걱정이었다.

다행히 위의 드라이브 문제를 해결하고 나니까 gpt에서 준 코드가 잘 맞았다.

 

 

최종 코드

코드에 대해 설명을 먼저 하자면, 패스 부분에서 a[n]부분이 한페이지당 16개씩 존재했다.

그리고 이런 페이지들이 총 15 페이지로 만들어져 있었다.

그래서 이 부분들을 각각 반복문으로 만들어야 했고, 그 안에 내용은 장소명과 주소명이 모두 담겨야 했다.

그리고 최종적으로는 이 코드들을 다 모아서 하나의 엑셀 파일에 저장하는 것을 목표로 했다.

엑셀파일로 만들면 시각화를 기반으로 할 때 쉬울 것 같았다.

 

코드를 따라하기 앞서 이전의 셀레니움과 관련된 포스팅을 보고오는 것을 추천한다.

 

2023.08.08 - [python] - [selenium] 웹사이트에서 데이터 긁어오기 - 이미지편

 

[selenium] 웹사이트에서 데이터 긁어오기 - 이미지편

오늘은 셀레니움을 이용해서 웹 사이트에서 사진을 다운받아오는 과정에 대해 작성한다. 이미지 분석에 사용할 수 있도록 예제코드를 배운 셈으로 생각보다 간단했다. 나는 주피터노트북 가상

forky-develop.tistory.com

2023.08.08 - [python] - [selenium] 웹사이트에서 데이터 긁어오기 - 실시간 검색어편

 

[selenium] 웹사이트에서 데이터 긁어오기 - 실시간 검색어편

이전에 이미지를 다운받을 수 있도록 코드를 짜는 것을 해봤으면, 이번엔 실시간 검색어 자체를 가져오는 것을 해보자 이미지 다운에 관련해서 궁금하다면 아래 링크로 들어가보면 된다. 2023.08.

forky-develop.tistory.com

 

 

1. 세팅

 

먼저 크롬 드라이브를 설정해주고, 셀레니움을 설치해야 한다.

# Set up for running selenium in Google Colab
## You don't need to run this code if you do it in Jupyter notebook, or other local Python setting
%%shell
sudo apt -y update
sudo apt install -y wget curl unzip
wget http://archive.ubuntu.com/ubuntu/pool/main/libu/libu2f-host/libu2f-udev_1.1.4-1_all.deb
dpkg -i libu2f-udev_1.1.4-1_all.deb
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
dpkg -i google-chrome-stable_current_amd64.deb
CHROME_DRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`
wget -N https://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip -P /tmp/
unzip -o /tmp/chromedriver_linux64.zip -d /tmp/
chmod +x /tmp/chromedriver
mv /tmp/chromedriver /usr/local/bin/chromedriver
pip install selenium

 

다음으로 Chrome WebDriver의 버전 관리 및 자동 설치를 위한 코드를 실행 시켜준다.

!pip install chromedriver-autoinstaller

 

여기까지 왔다면, 크롬 드라이브의 패스를 정해주고 셀레니움 버전을 확인해보자

import sys
sys.path.insert(0,'/usr/lib/chromium-browser/chromedriver')

import time
import pandas as pd
from bs4 import BeautifulSoup
import selenium
from selenium import webdriver
import chromedriver_autoinstaller

print(selenium.__version__)

 

크롬 드라이브의 패스가 설정되었으니, 셀레니움을 사용해서 크롬드라이브를 설정하고 초기화하는 코드를 작성한다.

# setup chrome options
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless') # ensure GUI is off
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')

# set path to chromedriver as per your configuration
chromedriver_autoinstaller.install()

# set up the webdriver
driver = webdriver.Chrome(options=chrome_options)
print(driver)

 

 

2. 코드 구현

여기까지 왔다면 모든 세팅은 끝났다!!

이제부터는 중요한 코드 부분을 마무리해야한다.

import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 1부터 15까지 반복
for m in range(1, 16):
    # URL 생성
    url = f"https://www.xn--2z1bw8k1pjz5ccumkb.kr/edc/crse/place.do?punit=5&psize=12&m1=&m2=&m3=&m4=&pno={m}&sch_area_cd=101&sch_signgu_cd=&sch_oper_sttus_se_cd=&sch_edc_plc_se_cd=&sch_edc_place_nm=#"

    # 해당 URL로 이동
    driver.get(url)

    # 페이지 스크롤 다운 (모든 장소 정보를 로드하기 위해)
    for i in range(3):  # 예를 들어 3번 스크롤 다운
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
        time.sleep(2)  # 스크롤 후 로딩을 위해 잠시 대기

    # 장소명과 주소를 저장할 리스트 초기화
    place_names = []
    addresses = []

    # 장소 정보 추출
    elements = driver.find_elements(By.XPATH, "//p[@class='title ellip']")
    for element in elements:
        place_names.append(element.text)

    address_elements = driver.find_elements(By.XPATH, "//li[@class='ellip']")
    for element in address_elements:
        addresses.append(element.text)

    # 장소명과 주소 출력
    for name, address in zip(place_names, addresses):
        print(f"장소명: {name}, 주소: {address}")
        
# WebDriver 종료
# driver.quit()

 

나의 경우 다음과 같이 했다.

이 부분만 사용할 사람들은 마지막에 주석처리된 크롬 드라이브 종료 코드를 같이 실행시켜주면 된다.

 

 

 

크롤링 관련해서 찾아본다고 생각보단 시간이 조금 걸렸지만, 뿌듯한 오전이었다.

728x90
반응형