본문 바로가기
  • Thank you for visiting.....
IT 지식

파이썬 네이버 지도 크롤링!

by HyunSoooo 2024. 7. 10.
728x90

 

클롤링 시연

 

 

import json
import re
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
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

# 찾은 ChromeDriver 경로를 여기에 설정
chrome_driver_path = "/Users/kimhyunsu/Downloads/chromedriver-mac-arm64/chromedriver"

def clean_text(text):
    # 이모티콘, 정량 표기, 예약 관련 단어 등을 제거하는 정규 표현식
    text = re.sub(r'[^\w\s]', '', text)  # 특수문자 및 이모티콘 제거
    text = re.sub(r'\d+g|\d+ml|\d+kg', '', text)  # 정량 표기 제거
    text = re.sub(r'예약|문의', '', text)  # 예약 관련 단어 제거
    text = re.sub(r'안내|전화', '', text)  # 안내 전화 관련 단어 제거
    return text.strip()

def get_menu(data):
    # ChromeDriver 인스턴스 생성
    chrome_options = Options()
    chrome_options.add_argument("--start-maximized")
    service = Service(chrome_driver_path)
    driver = webdriver.Chrome(service=service, options=chrome_options)
    
    try:
        driver.get("https://map.naver.com/v5/search/" + data)
        time.sleep(3)
        driver.implicitly_wait(3)

        # 검색 결과 프레임으로 전환
        try:
            WebDriverWait(driver, 10).until(
                EC.frame_to_be_available_and_switch_to_it((By.ID, 'searchIframe'))
            )
            print("검색 결과 프레임으로 전환했습니다.")
        except Exception as e:
            print(f"검색 결과 프레임으로 전환하는 데 실패했습니다: {e}")
            return -1

        # 가게 리스트를 가져옴
        try:
            temp = WebDriverWait(driver, 10).until(
                EC.presence_of_element_located((By.XPATH, '//*[@id="_pcmap_list_scroll_container"]/ul'))
            )
            print("가게 리스트를 성공적으로 가져왔습니다.")
        except Exception as e:
            print(f"가게 리스트를 가져오는 데 실패했습니다: {e}")
            return -1

        # 가게 링크를 가져옴
        try:
            button = temp.find_elements(By.TAG_NAME, 'a')
            driver.implicitly_wait(20)
            print("가게 링크를 성공적으로 가져왔습니다.")
        except Exception as e:
            print(f"가게 링크를 가져오는 데 실패했습니다: {e}")
            return -1

        # 가게 정보 클릭
        try:
            if '이미지수' in button[0].text or button[0].text == '':
                button[1].send_keys(Keys.ENTER)
            else:
                button[0].send_keys(Keys.ENTER)
            driver.implicitly_wait(3)
            time.sleep(3)
            print("가게 정보를 성공적으로 클릭했습니다.")
        except Exception as e:
            print(f"가게 정보를 클릭하는 데 실패했습니다: {e}")
            return -1

        # 기본 프레임으로 전환
        driver.switch_to.default_content()

        # 메뉴 탭 클릭
        try:
            WebDriverWait(driver, 10).until(
                EC.frame_to_be_available_and_switch_to_it((By.ID, 'entryIframe'))
            )
            menu_tab = WebDriverWait(driver, 10).until(
                EC.element_to_be_clickable((By.XPATH, '//a[@class="tpj9w _tab-menu" and .//span[text()="메뉴"]]'))
            )
            menu_tab.click()
            driver.implicitly_wait(3)
            print("메뉴 탭을 성공적으로 클릭했습니다.")
        except Exception as e:
            print(f"메뉴 탭을 클릭하는 데 실패했습니다: {e}")
            return -1

        # 메뉴 정보를 가져옴
        menu_list = []
        try:
            menu_items = driver.find_elements(By.CSS_SELECTOR, 'ul li.E2jtL')
            if not menu_items:
                print('메뉴가 없습니다')
                return -1

            for item in menu_items:
                try:
                    name = item.find_element(By.CSS_SELECTOR, 'div.yQlqY span.lPzHi').text
                    name = clean_text(name)  # 데이터 클리닝
                except:
                    name = 'N/A'
                menu_list.append({
                    'name': name
                })
    
            return menu_list
        except Exception as e:
            print(f"메뉴 정보를 가져오는 데 실패했습니다: {e}")
            return -1
    finally:
        driver.quit()  # ChromeDriver 종료를 finally 블록에 추가

def update_json_with_menus(file_path):
    # JSON 파일 로드
    with open(file_path, 'r', encoding='utf-8') as file:
        data = json.load(file)
        print(data)

    # 식당명으로 메뉴 정보 크롤링 및 JSON 업데이트
    for restaurant in data['식당목록']:  # '식당목록'을 JSON 구조에 맞게 변경하세요
        식당명 = restaurant.get('식당명')
        print('ㅇㅇㅇㅇㅇㅇ' + 식당명)
        if 식당명:
            print(f"{식당명}의 메뉴 정보를 가져오는 중...")
            메뉴 = get_menu(식당명)
            print(메뉴)
            if 메뉴 != -1:
                restaurant['메뉴'] = 메뉴

    # JSON 파일 저장
    with open(file_path, 'w', encoding='utf-8') as file:
        json.dump(data, file, ensure_ascii=False, indent=4)

# 사용 예시
file_path = 'search_place_lunch_map_results.json'
update_json_with_menus(file_path)
 

가계이름을 입력하면 해당 가게의 메뉴를 찾아줍니다!
단 주문 버튼이 생기는 메뉴등 좀 다른구조일경우 오류가 생기니깐 응용해서 사용하시면 좋을것같아요~

 

 

 

그리고 태그가 자주 바뀌므로 이것도 찾아야하고.. 클로링은 생각보다 쉽지않아요..

728x90

'IT 지식' 카테고리의 다른 글

POJO(Plain Old Java Object)  (0) 2024.04.18
소프트웨어 디자인의 빌더 패턴 이해  (0) 2024.03.27
Java의 ObjectMapper 이해  (0) 2024.03.26
이클립스 실행이 안될때 해결법  (1) 2024.03.14
SOAP(Simple Object Access Protocol)  (0) 2024.02.20