ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Selenium] 파이썬 셀레니움을 이용한 네이버 지도 크롤링 프로그램 만들기 - 2
    Python/크롤링 2024. 3. 5. 18:23
    반응형

    파이썬 셀레니움을 이용한 네이버 지도 크롤링 프로그램 만들기


    이전에 파이썬 셀레니움(Python Selenium)을 이용해서 네이버 지도에 등록된 업체 정보를 크롤링해보았습니다. 그런데, 이전에 작성한 코드에는 두 가지 문제가 있어서 완전한 크롤링을 할 수 없다는 단점이 있었지요.

     

    1. 네이버 지도는 한 페이지에 50건의 업체를 보여줍니다만, 스크롤을 내리지 않으면 일부분만 보여줍니다.
    2. 업체 세부정보를 보기 위해서는 해당 업체를 클릭해야 합니다.

    그래서, 위에 언급된 두 가지 문제를 해결하는 코드를 이용해서 새로운 크롤링 프로그램을 만들어 보도록 하겠습니다. 이번에는 셀레니움을 이용한 동적 크롤링뿐만 아니라 뷰티풀수프(BeautifulSoup)를 이용한 정적 크롤링까지 병행해서 이용해 보겠습니다.

     

    # import package
    import pandas as pd
    from selenium import webdriver
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By
    import time
    from bs4 import BeautifulSoup
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.ui import WebDriverWait
    
    # run webdriver
    driver = webdriver.Chrome()
    keyword = '서울 강남구 정보통신'
    url = f'https://map.naver.com/p/search/{keyword}'
    driver.get(url)
    action = ActionChains(driver)
    
    naver_res = pd.DataFrame(columns=['업체명','업종','주소','URL'])
    last_name = ''

     

     

    프레임 이동 구현


    네이버 지도 웹페이지는 검색 결과가 노출되는 영역(searchIframe)과 업체 세부 정보가 노출되는 영역(entryIframe)이 구분되어 있습니다. 그래서, 해당 영역을 이용할 때마다 webdriver.switch_to_.frame() 함수를 이용해서 이용할 프레임 변경을 해 줘야 합니다. 예를 들어,

     

    • searchIframe을 이용하기 위해서는 driver.switch_to.frame("searchIframe")
    • entryIframe을 이용하기 위해서는 driver.switch_to.frame(driver.find_element(By.XPATH, '//*[@id="entryIframe"]'))
    • 다른 프레임으로 이동하기 전 웹페이지 기본 프레임으로 이동하기 위해서는 driver.switch_to.default_content()

     

    을 이용할 수 있습니다. 각 프레임 이름은 크롬의 개발자 도구를 이용해 조회해볼 수 있습니다.

     

    def search_iframe():
        driver.switch_to.default_content()
        driver.switch_to.frame("searchIframe")
    
    def entry_iframe():
        driver.switch_to.default_content()
        WebDriverWait(driver, 2).until(EC.presence_of_element_located((By.XPATH, '//*[@id="entryIframe"]')))
    
        for i in range(5):
            time.sleep(.5)
    
            try:
                driver.switch_to.frame(driver.find_element(By.XPATH, '//*[@id="entryIframe"]'))
                break
            except:
                pass
    
    def chk_names():
        search_iframe()
        elem = driver.find_elements(By.XPATH, '//*[@id="_pcmap_list_scroll_container"]/ul/li/div[1]/div/a[1]/div/div/span[1]')
        name_list = [e.text for e in elem]
    
        return elem, name_list

     

    크롤링 구현하기


    네이버 지도 정보를 크롤링하기 위해, 파이썬으로 각 객체 이름을 클릭하고 세부정보 HTML 코드를 파싱하는 작업을 거칩니다. 각 업체별 이름은 사전 정의한 chk_names()를 이용해 구현하며, 반복문으로 해당 리스트를 클릭해주는 작업을 진행합니다. 세부정보가 조회된 뒤에는, 뷰티풀수프를 이용해 각 정보가 있는 코드의 클래스 이름을 지정해준 뒤, 해당 내용의 텍스트 정보를 저장하는 방식으로 동작합니다. 저장하는 정보는 업체명, 업종, 주소, 업체 URL입니다.

     

    def crawling_main():
        global naver_res
        addr_list = []
        category_list = []
        url_list = []
    
        for e in elem:
            e.click()
            entry_iframe()
            soup = BeautifulSoup(driver.page_source, 'html.parser')
    
            # append data
            try:
                category_list.append(soup.select('span.DJJvD')[0].text)
            except:
                category_list.append(float('nan'))
            try:
                addr_list.append(soup.select('span.LDgIH')[0].text)
            except:
                addr_list.append(float('nan'))
            try:
                url_list.append(soup.select('a.place_bluelink.CHmqa')[0]['href'])
            except:
                url_list.append(float('nan'))
    
            search_iframe()
    
        naver_temp = pd.DataFrame([name_list,category_list,addr_list,url_list], index=naver_res.columns).T
        naver_res = pd.concat([naver_res, naver_temp])
        naver_res.to_excel('./naver_crawling_result.xlsx')

     

    자동 스크롤


    네이버 지도에서 업체 정보를 스크롤해서 각 페이지마다 50개의 업체 정보를 모두 로드하는 과정을 구현합니다. 이 때는 webdriver.ActionChains를 이용해서 각 페이지별로 맨 끝에 로드된 업체가 보일 때까지 화면을 옮겨주는 방식을 구현해 봤습니다. 예를 들어, 10번째 항목이 있는 곳으로 이동하면 그 20번째 정보까지 로드되고, 다음에는 20번째 항목이 있는 곳으로 이동해서 30번째까지 로드되고... 하는 방식이지요.

     

    페이지 이동


    각 페이지를 이동하는 방법은 이전에 작성했던 파이썬 셀레니움을 이용한 네이버 지도 크롤링 프로그램 만들기 문서와 같습니다. 네이버 지도는 다음 버튼을 누르면 항상 한 페이지씩 이동하는 특징을 보이고 있는데, 이를 이용해서 계속 다음 버튼을 눌러주는 방식이죠. 만약 마지막 페이지까지 이동했다면, 이전 페이지와 같은 정보를 보이는지 확인한 뒤 종료하는 방법을 구현했습니다.

     

    page_num = 1
    
    while 1:
        time.sleep(.5)
        search_iframe()
        elem, name_list = chk_names()
        if last_name == name_list[-1]:
            pass
    
        while 1:
            # auto scroll
            action.move_to_element(elem[-1]).perform()
            elem, name_list = chk_names()
    
            if last_name == name_list[-1]:
                break
            else:
                last_name = name_list[-1]
    
        crawling_main()
    
        # next page
        driver.find_element(By.XPATH, '//*[@id="app-root"]/div/div[2]/div[2]/a[7]').click()
        time.sleep(1.5)

     

    반응형

    댓글

문의: jwkang3929@naver.com