Google Sheets 활용법/ReviewChecker

ReviewCheck (3) - 네이버카페 HTML을 분석해보자!

Mr.Lazy 2024. 7. 5. 16:43

 

지난 글에서는 파이썬을 통해 구글시트를 조회, 편집하는 기능을 구현해 보았습니다.

이번 글에서는 구글시트의 링크에 접속하여 본문의 내용을 가져오는 코드를 알려드리겠습니다.


 

이제 구글 시트에 있는 링크에 접속해서 해당 링크의 본문이 어느 부분에 적혀있는지 컴퓨터에게 알려줘야 컴퓨터가 그 부분을 읽어올수 있기 때문에 사이트 구조를 파악해야합니다.

 

 

 

사이트는 기본적으로 HTML, CSS, JavaScript로 이뤄져 있는데 사실 저도 자세히는 모릅니다.

간단하게 설명하면 아래 그림과 같다고 합니다.- HTML : 뼈- CSS : 피부, 모발 등
- JavaScript : 근육

 

 

궁금하신 분은 아래 링크나 검색해보시면 여러 똑똑하신 분들이 많이 알려주시기 때문에 생략하도록 하겠습니다.

 

https://velog.io/@memoyoon/1%EC%A3%BC%EC%B0%A8.-HTML-CSS-JavaScript%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B4%EB%A9%B0-%ED%95%84%EC%9A%94%ED%95%9C-%EC%9D%B4%EC%9C%A0

https://whdgus928.tistory.com/104


그럼 우리는 이제 본문이 HTML(뼈대) 중 어느 부분이 있는지 알아야합니다!

 

이 밑은 제가 GPT를 통해 만든 코드입니다.

(크롬이 만드시 설치되어 있어야합니다!)

 

★설치해야할 라이브러리Visual Studio Code - Terminal에 입력

pip install selenium webdriver-manager

 

★ 네이버, 다음 로그인을 해야하는 링크의 경우

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
import pickle
import os

def save_cookies(login_url, cookies_file_path, domain_key):
    # 크롬 드라이버 설정
    options = webdriver.ChromeOptions()
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--ignore-certificate-errors')  # SSL 오류 무시
    options.add_argument('--ignore-ssl-errors')  # SSL 오류 무시

    # 웹 드라이버 설정
    driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
    
    try:
        # 로그인 페이지 열기
        driver.get(login_url)

        # 수동으로 로그인 수행
        print(f"{domain_key} 로그인을 완료한 후 엔터 키를 누르세요...")
        input()

        # 기존 쿠키 로드
        if os.path.exists(cookies_file_path):
            with open(cookies_file_path, 'rb') as f:
                all_cookies = pickle.load(f)
        else:
            all_cookies = {}

        # 새로운 쿠키 저장
        cookies = driver.get_cookies()
        all_cookies[domain_key] = cookies
        with open(cookies_file_path, 'wb') as f:
            pickle.dump(all_cookies, f)
        print(f"{domain_key} 쿠키가 {cookies_file_path}에 저장되었습니다.")

    except Exception as e:
        print(f"오류 발생: {e}")

    finally:
        # 드라이버 종료
        driver.quit()
        print("드라이버 종료 완료")

def save_webpage_html_to_txt(url, cookies_file_path, html_file_path):
    # 크롬 드라이버 설정
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')  # 필요 시 주석 처리
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--ignore-certificate-errors')  # SSL 오류 무시
    options.add_argument('--ignore-ssl-errors')  # SSL 오류 무시

    # 웹 드라이버 설정
    driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)

    try:
        # 페이지 열기
        driver.get(url)

        # 적절한 도메인 키 선택
        if "naver.com" in url:
            domain_key = "naver"
        elif "daum.net" in url:
            domain_key = "daum"
        else:
            print("지원하지 않는 도메인입니다.")
            return

        # 쿠키 로드
        with open(cookies_file_path, 'rb') as f:
            all_cookies = pickle.load(f)
            cookies = all_cookies.get(domain_key, [])

        for cookie in cookies:
            if 'sameSite' in cookie:
                del cookie['sameSite']  # 이 속성은 필요하지 않습니다.
            if 'expiry' in cookie:
                del cookie['expiry']  # expiry 속성은 유효기간이 지나면 필요없습니다.
            cookie['domain'] = '.naver.com' if "naver.com" in url else '.daum.net'  # 쿠키의 도메인을 명시적으로 설정
            driver.add_cookie(cookie)

        # 페이지 새로고침
        driver.get(url)

        # 네이버의 경우 iframe으로 전환
        if "naver.com" in url:
            WebDriverWait(driver, 30).until(
                EC.frame_to_be_available_and_switch_to_it((By.ID, 'cafe_main'))
            )

        # 본문 내용이 로드될 때까지 대기
        WebDriverWait(driver, 30).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "div.se-main-container"))
        )

        # 페이지 소스 가져오기
        html = driver.page_source

        # HTML 값을 파일에 저장
        with open(html_file_path, 'w', encoding='utf-8') as f:
            f.write(html)

        print(f"HTML 소스가 {html_file_path}에 저장되었습니다.")

    except Exception as e:
        print(f"오류 발생: {e}")

    finally:
        # 드라이버 종료
        driver.quit()
        print("드라이버 종료 완료")

# 네이버 로그인 및 쿠키 저장
naver_login_url = "https://nid.naver.com/nidlogin.login"
cookies_file_path = "cookies.pkl"
save_cookies(naver_login_url, cookies_file_path, "naver")

# 다음 로그인 및 쿠키 저장
daum_login_url = "https://logins.daum.net/accounts/loginform.do"
save_cookies(daum_login_url, cookies_file_path, "daum")

# URL을 직접 지정
url = "여기에 링크 입력"  # 여기에 원하는 URL을 입력하세요
desktop_path = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop')
html_file_path = os.path.join(desktop_path, 'webpage_content.txt')

# HTML 저장
save_webpage_html_to_txt(url, cookies_file_path, html_file_path)

print("종료!")

 

★ 로그인이 필요없는 링크의 경우

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
import os

def save_webpage_html_to_txt(url, html_file_path):
    # 크롬 드라이버 설정
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')  # 필요 시 주석 처리
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--ignore-certificate-errors')  # SSL 오류 무시
    options.add_argument('--ignore-ssl-errors')  # SSL 오류 무시

    # 웹 드라이버 설정
    driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)

    try:
        # 페이지 열기
        driver.get(url)

        # 네이버의 경우 iframe으로 전환
        if "naver.com" in url:
            WebDriverWait(driver, 30).until(
                EC.frame_to_be_available_and_switch_to_it((By.ID, 'cafe_main'))
            )

        # 본문 내용이 로드될 때까지 대기
        WebDriverWait(driver, 30).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "div.se-main-container"))
        )

        # 페이지 소스 가져오기
        html = driver.page_source

        # HTML 값을 파일에 저장
        with open(html_file_path, 'w', encoding='utf-8') as f:
            f.write(html)

        print(f"HTML 소스가 {html_file_path}에 저장되었습니다.")

    except Exception as e:
        print(f"오류 발생: {e}")

    finally:
        # 드라이버 종료
        driver.quit()
        print("드라이버 종료 완료")

# URL을 직접 지정
url = "여기에 링크 입력"  # 여기에 원하는 URL을 입력하세요
desktop_path = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop')
html_file_path = os.path.join(desktop_path, 'webpage_content.txt')

# HTML 저장
save_webpage_html_to_txt(url, html_file_path)

print("종료!")

 

 

두가지 버전 중 원하시는 버전을 사용하시면 됩니다.

 

원하시는 링크가 로그인이 필요한 경우는 첫번째, 로그인이 필요없는 경우는 두번째 코드를 사용하시면 됩니다.


사용법

 

우선 Visual Studio Code에 들어가 New File을 만들겠습니다. 

저는 htmlmaker.py로 만들겠습니다.

 

그 후 Terminal - New Terminal를 누르고 Terminal에 아래 코드를 입력하고 Enter!

pip install selenium webdriver-manager

 

 

라이브러리 설치가 완료 되었다면 htmlmaker.py에 코드를 입력해보겠습니다.

로그인이 필요하신 카페의 구조가 궁금하실 경우 첫번째 코드를 아닐 경우 두번째 코드를 사용하시면 됩니다.

(네이버, 다음 카페, 블로그들의 경우 같은 플랫폼일 경우 구조가 모두 동일하므로 로그인이 필요없는 카페의 글로 구조를 파악해도 무방합니다.)

 

우선 로그인이 필요한 경우 먼저 실행해보겠습니다.

 

먼저 코드내 이 부분 작은따옴표안에 원하시는 링크를 입력합니다.

url = "여기에 링크 입력"  # 여기에 원하는 URL을 입력하세요

 

그 후 실행해보겠습니다.

크롬을 통해 로그인 창이 열리고 로그인 해주도록 합니다.

로그인을 한 후 Terminal로 돌아가 Enter를 누르겠습니다.

 

그럼 네이버 로그인된 창이 닫히고 다음 로그인 창이 열리게 됩니다.

 

다음도 로그인 해주겠습니다.

동일하게 로그인을 한 후 Terminal로 돌아가 Enter를 누르겠습니다.

 

 

그럼 마찬가지로 로그인된 창이 닫히고 좀 기다린다면 파일이 저장될것입니다.

 

 

 

바탕 화면에 잘 저장된것을 확인할수 있습니다. 파일을 한번 열어보겠습니다.

 

 

엄청 복잡합니다;; 여기서 본문의 내용을 한번 찾아볼까요?

 

 

제가 입력한 링크 본문의 첫줄입니다. 메모장에 검색해볼까요?

 

 

해당 사이트 HTML의 이부분에 본문의 내용이 있는 것을 파악할수 있습니다!

 

로그인이 필요하지 않은 버전은 로그인 없이 아래 코드에 링크만 입력하시고 실행하면 바탕화면에 동일하게 HTML 파일이 저장되게 됩니다.

url = "여기에 링크 입력"  # 여기에 원하는 URL을 입력하세요

 

여기까지 진행하셔서 HTML을 메모장 파일로 저장하셨다면 본문의 내용을 한번 출력해볼까요?

from bs4 import BeautifulSoup

# 파일 경로 설정
file_path = r"여기에 HTML 메모장 파일 경로 입력"

# 파일 읽기
with open(file_path, 'r', encoding='utf-8') as file:
    html_content = file.read()

# BeautifulSoup 객체 생성
soup = BeautifulSoup(html_content, 'html.parser')

# 본문 내용이 있는 div 태그 찾기
content_div = soup.find('div', class_='content CafeViewer')

# 본문 내용 추출
if content_div:
    # 모든 p 태그의 텍스트를 추출하여 합치기
    paragraphs = content_div.find_all('p')
    content_text = '\n'.join(paragraph.get_text(strip=True) for paragraph in paragraphs)
    
    # 결과 출력
    print(content_text)
else:
    print("본문 내용을 찾을 수 없습니다.")

 

파이썬 파일을 하나 만들고 해당 코드를 입력해서 실행해볼까요?

아래 코드에 메모장 파일의 경로를 입력하면 됩니다.

# 파일 경로 설정
file_path = r"여기에 HTML 메모장 파일 경로 입력"

 

 

실행 결과 본문이 잘 확인되네요.

본문을 확인하는 코드는 네이버카페 링크에서 가져온 HTML 파일에만 적용이 됩니다.

다른 다음카페나 블로그의 경우 HTML 구조가 달라서 다른 코드를 만드셔야합니다.

(GPT에게 물어보는 것 추천)

 

↓아래는 제가 GPT에게 질문한 내용입니다.

(저는 메모장 첨부했지만 GPT3.5를 사용하시는 경우 본문 내용의 부분만 복붙하시면 됩니다.)

여기 고객님이 작성한 후기 링크의 HTML인데 본문의 내용이 어느위치에 있는지 파악해볼래?
그후 해당 HTML에서 본문만 추출하는 파이썬 코드를 만들어줄래?

경로는 여기 있어

"HTML 파일 경로 입력"

 

HTML 구조를 파악하는 방법을 찾아보니 여러가지가 나왔지만 저는 아무리 봐도 어려워서 GPT와 함께 코드를 만들었습니다.

 

네이버, 다음 카페 뿐 아니라 다른 사이트들의 링크도 사용가능하기 때문에 사용해보시기를 바랍니다!

 


 

다음 시간에는 구글시트에 입력된 링크에 들어가 본문 위치에 있는 글의 수를 파악해 조건에 부합한 후기인지 아닌지를 구글시트에 작성하는 코드를 만들어보겠습니다!

다음글에서 또 봐요~ (*ˊᵕˋ*)ノ

 

진행하시면서 막히는 부분이나 궁금한 점 있으실 경우 댓글이나 아래 메일로 여쭤보시면 열심히 답변드려보도록 하겠습니다!

- amos1592@naver.com