네이버 지도 크롤링 [셀레니움(selenium)]

728x90

안녕하세요!

오늘은 셀레니움을 이용한 네이버 지도 크롤링을 해보도록 하겠습니다.

 

 

 

1. 네이버 지도 구조 파악

셀레니움을 사용해서 크롤링을 하기 전에 네이버 지도의 구조를 확인해 보겠습니다.

저는 특정 지역의 음식점 정보를 크롤링할 예정이고 네이버지도는 2개의 프레임으로 나누어져 있습니다.

 

 

왼쪽 searchIframe과 오른쪽 entryIframe으로 구분이 됩니다.

왼쪽 프레임에서는 검색을 하게 되고 오른쪽 프레임에서는 상세 정보를 확인하게 됩니다. 

계속 프레임이 전환되면서 크롤링을 해야 합니다

 

 

 

 

2. 크롤링하기 

 

import selenium #셀레니움
import pandas as pd #csv를 읽고 dataframe을 사용하기 위한 pandas
from selenium import webdriver #브라우저를 띄우고 컨트롤하기 위한 webdriver
from selenium.webdriver.common.keys import Keys #브라우저에 키입력 용
from selenium.webdriver.common.by import By #webdriver를 이용해 태그를 찾기 위함
from selenium.webdriver.support.ui import WebDriverWait #Explicitly wait을 위함
from webdriver_manager.chrome import ChromeDriverManager #크롬에서 크롤링 진행 크롬 웹 드라이버 설치시 필요
from selenium.webdriver.support import expected_conditions as EC #브라우저에 특정 요소 상태 확인을 위해
from bs4 import BeautifulSoup #브라우저 태그를 가져오고 파싱하기 위함
from selenium.common.exceptions import NoSuchElementException,StaleElementReferenceException,TimeoutException #예외처리를 위한 예외들 
import time
import re


driver = webdriver.Chrome()
driver.get("https://map.naver.com/v5/search")


# 검색창에 검색어 입력하기
search_box = driver.find_element(By.CSS_SELECTOR, "div.input_box>input.input_search")
search_box.send_keys("제주도 식당")

time.sleep(3)

# 검색버튼 누르기
search_box.send_keys(Keys.ENTER)
time.sleep(1)


#검색 프레임으로 이동
driver.switch_to.frame("searchIframe")

#스크롤 클릭
driver.find_element(By.CSS_SELECTOR, "#_pcmap_list_scroll_container").click()

# 리스트(li태그) 가져오기
litags = driver.find_elements(By.CSS_SELECTOR, '#_pcmap_list_scroll_container>ul>li.UEzoS.rTjJo')

before_len = len(litags)

while True:
    # 스크롤을 내려 리스트를 더 가져온다.
    driver.find_element(By.CSS_SELECTOR, 'body').send_keys(Keys.END)
    time.sleep(2)
    
    litags = driver.find_elements(By.CSS_SELECTOR, '#_pcmap_list_scroll_container>ul>li.UEzoS.rTjJo')
    
    # 스크롤 후 li의 수
    total_len = len(litags)
       
    if before_len == total_len:
        break
        
    before_len = total_len
    
    
for litag in litags:
    
    litag.find_element(By.CSS_SELECTOR, "span.TYaxT").click()
    driver.switch_to.default_content()
    time.sleep(7) 
    
    # entryIframe 로드를 기다림
    WebDriverWait(driver, 10).until(
            EC.frame_to_be_available_and_switch_to_it((By.ID, "entryIframe"))
        )
    
    try:

        # entryIframe 내에서 정보 추출
        name = driver.find_element(By.CSS_SELECTOR, "span.Fc1rA").text
        print(name)
        address = driver.find_element(By.CSS_SELECTOR, "span.LDgIH").text
        print(address)
        road_address = driver.find_element(By.CSS_SELECTOR, "span.LDgIH").text
        print(road_address)
        tag = driver.find_element(By.CSS_SELECTOR, "div.xPvPE").text
        print(tag)
        introduction = driver.find_element(By.CSS_SELECTOR, "span.zPfVt").text
        print(introduction)
        phone_number = driver.find_element(By.CSS_SELECTOR, "span.xlx7Q").text
        print(phone_number)



        # CSS 선택자를 사용하여 div 요소를 찾고 style 속성 가져오기
        div_element = driver.find_element(By.CSS_SELECTOR, "div.K0PDV._div")
        div_style = div_element.get_attribute('style')

        # 정규 표현식을 사용하여 URL 추출
        url_match = re.search(r'url\("([^"]+)"\)', div_style)
        if url_match:
            image_url = url_match.group(1)
            print(image_url)  # 이미지 URL 출력


        all_tag = driver.find_element(By.CSS_SELECTOR, "span.PXMot").text
    
    except NoSuchElementException:
        introduction =""
   
    
    driver.switch_to.default_content()
    
    # 다시 searchIframe으로 전환
    WebDriverWait(driver, 10).until(
            EC.frame_to_be_available_and_switch_to_it((By.ID, "searchIframe"))
        )

크롤링을 할 때 좀 시간을 많이 사용했던 점은 로딩으로 발생하는 오류와 프레임의 전환이었습니다.

시간은 sleep를 적당히 사용하면 됩니다. 

프레임의 전환은  driver.switch_to.default_content() 를 사용해야지 오른쪽 프레임을 제대로 잡을 수 있습니다. 

로딩 시간 동안 오류를 방지하기  위해     WebDriverWait(driver, 10).until( EC.frame_to_be_available_and_switch_to_it((By.ID, "entryIframe"))) 을 사용해서 프레임이 전환되기까지 기다리도록 하였습니다.

 

 

 

 

3.  NoSuchElementException

테스트하기 위해 해당 코드를 실행하니  NoSuchElementException 오류가 발생했습니다.     

엘리먼트 요소를 찾지 못해서 발생하는 오류로 try exceot를 사용하여 공백으로 처리하도록 하였습니다.

 

 

4. 결과

 

print가 잘되는 것을 확인할 수 있습니다.

데이터 프레임으로 append 하여 사용하거나 엑셀로 저장하면 됩니다.

 

 

다음에는 네이버 지도에서 위경도 정보를 가져오는 방법을 찾아볼 계획입니다.

728x90
반응형

'Python(파이썬)' 카테고리의 다른 글

Flask 외부 접속하기!  (1) 2023.10.11
Python module 'jwt' has no attribute 'decode' 오류  (0) 2023.10.11