상세 컨텐츠

본문 제목

크롤링 기능 사용하기 -하-

카테고리 없음

by 민초왕 2024. 10. 15. 06:47

본문

일단 앞에 상의 내용을 다 지워도 되는데 블ㄹ로그 채우기느낌으로 그냥 둘게

먼저 나는 네이버 map에서 리뷰 데이터를 가져와서 수치화를 하려고 했다.

그러면서 생기는문제 1번째. 어떠한 방식으로도 크롤링이 되질 않았다. 물론 내 코드에 문제가 있을 수 있지만,,,,,
알수 없는 원인이 있다랄까?

그래서 찾아보다가 플레이스로 크롤링이 가능하다는 점이 있어 이용한 사례등이 있었다.

 

그리하여 크롤링 https://m.place.naver.com/restaurant/{rest_num}/review/visitor?entry=ple&reviewSort=recent
여기서 보면 rest_num이 음식점마다 부여된 고유번호? 라고 해야하나.

아무튼 이제 음식점 번호만 따내면 된다. 번따를 시도해야하는데,,,, 방법이 떠오르지 않는다.

왜냐면 플레이스에서도 rest_num으로 검색해서 음식점 명으로는 한계가 있다.

그렇다고 map으로 가자니 링크도 안끌어와진다.
시간은 촉박해서 생각한 마지막 묘수....

 

그것은 검색 매크로만 만들고 내가 직접 복사 붙여넣기 하는것이다.

인간 크롤링...... 그래서 그냥 5초 마다 검색하게 하고 5초내로 복사 붙여넣기하는 말도 안되는 방법을 썼다.

 

그렇게 700개 정도를 가져왔고,  1시간 정도밖에 안걸리긴 했다. 인간승리.

그 후에 csv파일로 만들어서 크롤링을 진행했다.

 

다른사람 블로그에 있는 코드를 가져온 후에 수정해서 썼다.

 

 

 

일단 잠깐 올려놓고 나중에 다시 써야지.

 

 

 

 

import pandas as pd  # CSV 파일을 읽기 위해 pandas 추가
import chardet  # 인코딩 감지를 위해 chardet 임포트
from selenium.webdriver.common.by import By
from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter
from openpyxl import Workbook
from bs4 import BeautifulSoup
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.keys import Keys
import time
import datetime
import requests
from selenium.webdriver.chrome.service import Service
from datetime import datetime, timedelta  # 날짜 관련 임포트

# CSV 파일 경로 설정 (해결 방법 적용)
csv_path = r'C:\Users\user\Desktop\프로젝트\cookie.csv'  # cookie.csv 파일 경로

# BS4 설정을 위한 세션 생성
session = requests.Session()
headers = {
    "User-Agent": "user value"}  # User-Agent 설정 (필요시 변경)

# HTTP 요청에 대한 재시도 설정
retries = Retry(total=5,  # 최대 5번 재시도
                backoff_factor=0.1,  # 재시도 간 대기 시간
                status_forcelist=[500, 502, 503, 504])  # 재시도할 HTTP 상태 코드

# 세션에 재시도 정책 마운트
session.mount('http://', HTTPAdapter(max_retries=retries))

# 새로운 xlsx 파일 생성
now = datetime.now()  # 현재 시간 가져오기
xlsx = Workbook()  # 새로운 워크북 생성
list_sheet = xlsx.create_sheet('output')  # "output"이라는 이름의 시트 생성
list_sheet.append(['rest_num', 'nickname', 'content', 'date', 'revisit'])  # 헤더 추가

# 파일의 인코딩 감지
with open(csv_path, 'rb') as f:
    result = chardet.detect(f.read())
    encoding = result['encoding']

# 감지된 인코딩으로 CSV 파일 읽기
df = pd.read_csv(csv_path, encoding=encoding)  # CSV 파일을 데이터프레임으로 읽어오기

# 현재 날짜에서 1년 전 날짜 계산
one_year_ago = now - timedelta(days=365)

# 크롤링 시작
for index, row in df.iterrows():  # 각 행에 대해 반복
    rest_num = row['rest_num']  # rest_num 값 가져오기

    if rest_num == 1:  # rest_num이 1인 경우 건너뛰기
        print(f'Skipping rest_num: {rest_num} at index: {index}')
        continue  # 다음 행으로 넘어감

    # URL 설정: 크롤링할 네이버 맛집 리뷰 페이지
    url = f'https://m.place.naver.com/restaurant/{rest_num}/review/visitor?entry=ple&reviewSort=recent'

    # Webdriver의 headless 모드 설정
    options = webdriver.ChromeOptions()
    # options.add_argument('headless')  # 주석 처리되어 있어 UI를 보임
    options.add_argument('window-size=1920x1080')  # 브라우저 창 크기 설정
    options.add_argument("disable-gpu")  # GPU 사용 안 함

    try:
        # Chrome 드라이버 실행
        driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
        res = driver.get(url)  # 지정된 URL로 웹페이지 열기
        driver.implicitly_wait(30)  # 페이지 로드 대기

        # 페이지 다운 (스크롤을 내려 더 많은 리뷰를 로드)
        driver.find_element(By.TAG_NAME, 'body').send_keys(Keys.PAGE_DOWN)

        # 리뷰 더보기 버튼 클릭: 최대 1000번 반복
        for i in range(1000):  # 최대 1000번 반복
            try:
                driver.find_element(By.XPATH, '//*[@id="app-root"]/div/div/div/div[6]/div[2]/div[3]/div[2]/div/a').click()  # 더보기 버튼 클릭
                time.sleep(0.4)  # 클릭 후 잠시 대기
            except Exception as e:
                print('finish')  # 더 이상 리뷰가 없을 경우 종료 메시지 출력
                break  # 반복 종료

        time.sleep(25)  # 페이지 로딩 대기
        html = driver.page_source  # 페이지 소스 코드 가져오기
        bs = BeautifulSoup(html, 'lxml')  # BeautifulSoup 객체 생성
        reviews = bs.select('li.pui__X35jYm.EjjAW')  # 리뷰 리스트 선택

        # 각 리뷰에 대해 정보 추출
        for r in reviews:
            # nickname (닉네임) 추출
            nickname = r.select_one('div.pui__JiVbY3 > span.pui__uslU0d')

            # content (리뷰 내용) 추출
            content = r.select_one('div.pui__vn15t2 > a.pui__xtsQN-')

            # date (리뷰 날짜) 추출
            date_elements = r.select('div.pui__QKE5Pr > span.pui__gfuUIT > time')
            date = date_elements[0].text if date_elements else 'N/A'  # 존재 여부 체크

            # 날짜 형식 처리
            if date != 'N/A':
                try:
                    # 'YYYY-MM-DD' 형식 처리
                    date = datetime.strptime(date, '%Y-%m-%d')
                except ValueError:
                    try:
                        # 'MM.DD.요일' 형식 처리
                        date = datetime.strptime(date, '%m.%d.%a')
                        # 현재 연도 추가
                        date = date.replace(year=datetime.now().year)
                    except ValueError:
                        date = None  # 처리할 수 없는 경우 None으로 설정

            # revisit (재방문 여부) 추출
            revisit_span = r.select('div.pui__QKE5Pr > span.pui__gfuUIT')
            revisit = revisit_span[1].text if len(revisit_span) > 1 else 'N/A'  # 존재 여부 체크

            # 날짜가 1년 이내인 경우에만 추가
            if date and date >= one_year_ago:
                # 예외 처리: 값이 없을 경우 빈 문자열로 설정
                nickname = nickname.text if nickname else ''
                content = content.text if content else ''
                date = date.strftime('%Y-%m-%d') if date else ''
                revisit = revisit if revisit else ''
                time.sleep(0.06)  # 잠시 대기

                # 시트에 정보 추가 및 출력
                print(nickname, '/', content, '/', date, '/', revisit)  # 콘솔에 출력
                list_sheet.append([rest_num, nickname, content, date, revisit])  # 음식점 번호 추가
                time.sleep(0.06)  # 잠시 대기

        # 파일 저장
        file_name = 'naver_review_' + now.strftime('%Y-%m-%d_%H-%M-%S') + '.xlsx'  # 파일 이름 설정
        xlsx.save(file_name)  # 파일 저장

    except Exception as e:
        print(e)  # 오류 메시지 출력
        # 파일 저장 (임시)
        file_name = 'naver_review_' + now.strftime('%Y-%m-%d_%H-%M-%S') + '.xlsx'  # 파일 이름 설정
        xlsx.save(file_name)  # 파일 저장