Google Sheets 활용법/ReviewChecker

ReviewCheck (4) - 구글시트에 입력된 링크(리뷰 글)가 조건에 맞는지 체크해보자!

Mr.Lazy 2024. 7. 10. 11:15

지난 글에서는 파이썬을 통해 HTML의 구조를 파악해보았습니다.

그럼 우리는 이제 3개의 파일을 얻었는데요.

  • 구글 시트를 조회 편집하는 코드
  • 링크의 HTML을 추출하는 코드
  • 추출한 HTML에서 본문을 추출하는 코드

이 3가지 코드를 GPT에게 알려주고 적절히 조합해 원하는 코드를 만들어 달라고 해보겠습니다.


```
from oauth2client.service_account import ServiceAccountCredentials
import gspread
import requests
from bs4 import BeautifulSoup

# 구글 시트 API 사용을 위한 인증 정보 설정
scope = ['https://www.googleapis.com/auth/spreadsheets']
json_keyfile = r'키 파일의 경로 입력'

creds = ServiceAccountCredentials.from_json_keyfile_name(json_keyfile, scope)
client = gspread.authorize(creds)

# 구글 시트 문서 가져오기
spreadsheet_url = '구글시트 URL'
sheet = client.open_by_url(spreadsheet_url)

# 시트 이름으로 워크시트 선택
worksheet = sheet.worksheet('후기')

# E열의 링크 가져오기
column_e = worksheet.col_values(5)  # E열은 5번째 열

# 결과 출력
print("E열 데이터:")
for idx, cell in enumerate(column_e[1:], start=2):  # E열의 헤더를 건너뛰고 2번째 행부터 시작
    if cell:
        print(f"링크 {idx - 1}: {cell}")

        try:
            # 링크에 접속하여 HTML 가져오기
            response = requests.get(cell)
            response.raise_for_status()

            # BeautifulSoup을 사용하여 HTML 파싱
            soup = BeautifulSoup(response.content, 'html.parser')

            # 본문 내용 추출 (이전에 분석한 구조를 기반으로)
            content_div = soup.select_one('div.content.CafeViewer')
            if content_div:
                text_content = ''.join(p.get_text(strip=True) for p in content_div.find_all('p'))
                print(f"본문 글자 수: {len(text_content)}")

                # 글자 수가 100자 이상인지 확인하고 F열에 조건 통과 여부 표시
                if len(text_content) >= 100:
                    result = '통과'
                else:
                    result = '미통과'
            else:
                result = '본문 없음'
        except requests.exceptions.RequestException as e:
            print(f"요청 오류: {e}")
            result = '링크 오류'

        # F열에 결과 업데이트
        worksheet.update_cell(idx, 6, result)
        print(f"F{idx}에 {result} 작성 완료!")

print("모든 작업 완료!")
```

현재 내 코드인데 내 '후기'시트의 E2셀부터 아래로 후기 링크가 작성될거야.
그럼 링크에 접속해 링크의 본문을 확인한 다음 
본문 글자수가 100자 이상인지 확인하고 F2셀부터 조건 통과 여부를 표시해줄래?

```
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 = "https://cafe.naver.com/directwedding/6654382"  # 여기에 원하는 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("종료!")
```
↑링크를 확인하는 방법 참고

```
from bs4 import BeautifulSoup

# 파일 경로 설정
file_path = r"C:\Users\usb15\Desktop\webpage_content.txt"

# 파일 읽기
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("본문 내용을 찾을 수 없습니다.")
```
↑링크의 본문을 찾아내는 방법 참고

 

위 글 대로 GPT에게 질문을 했습니다.

 

첫번째 작성한 코드는 구글 시트를 조회 편집하는 코드를 알려주고 해당 코드를  아래 처럼 수정해달라고 했습니다.

- 현재 내 코드인데 내 '후기'시트의 E2셀부터 아래로 후기 링크가 작성될거야. 그럼 링크에 접속해 링크의 본문을 확인한 다음 본문 글자수가 100자 이상인지 확인하고 F2셀부터 조건 통과 여부를 표시해줄래?

 

두번째 작성한 코드(링크의 HTML을 추출하는 코드)를 보고 링크를 확인하는 방법을 참고하라고 했으며

세번째 작성한 코드(추출한 HTML에서 본문을 추출하는 코드)를 보고 본문의 내용을 찾는 방법을 참고하라고 지시했습니다.

 

↓GPT의 답변

 

필요한 라이브러리들을 설치하기 위해 pip 명령어를 사용할 수 있습니다. 다음은 해당 라이브러리들을 설치하는 데 필요한 명령어입니다.

pip install oauth2client gspread requests beautifulsoup4 selenium webdriver-manager

 

 

주어진 코드와 추가된 정보를 사용하여 링크의 본문 내용을 확인하고 글자 수가 100자 이상인지 확인한 다음, 결과를 F열에 표시하는 코드를 수정하겠습니다. Selenium을 활용하여 링크의 본문을 확인하고, BeautifulSoup을 사용하여 본문 내용을 추출한 후 조건에 맞게 결과를 업데이트하는 형태로 코드를 조정하겠습니다.

다음은 수정된 전체 코드입니다.

from oauth2client.service_account import ServiceAccountCredentials
import gspread
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
from bs4 import BeautifulSoup

# 구글 시트 API 사용을 위한 인증 정보 설정
scope = ['https://www.googleapis.com/auth/spreadsheets']
json_keyfile = r'키값 경로 입력'

creds = ServiceAccountCredentials.from_json_keyfile_name(json_keyfile, scope)
client = gspread.authorize(creds)

# 구글 시트 문서 가져오기
spreadsheet_url = '구글시트 URL 입력'
sheet = client.open_by_url(spreadsheet_url)

# 시트 이름으로 워크시트 선택
worksheet = sheet.worksheet('후기')

# E열의 링크 가져오기
column_e = worksheet.col_values(5)  # E열은 5번째 열

# Selenium을 사용하여 링크에서 HTML 가져오기
def get_page_content(url):
    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')
    options.add_argument('--ignore-ssl-errors')

    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, div.content.CafeViewer"))
        )
        
        html = driver.page_source
        return html

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

    finally:
        driver.quit()

# 본문 내용 추출
def extract_content(html):
    soup = BeautifulSoup(html, 'html.parser')
    content_div = soup.select_one('div.se-main-container, div.content.CafeViewer')
    
    if content_div:
        paragraphs = content_div.find_all('p')
        content_text = ''.join(p.get_text(strip=True) for p in paragraphs)
        return content_text
    else:
        return None

# 결과 출력
print("E열 데이터:")
for idx, cell in enumerate(column_e[1:], start=2):  # E열의 헤더를 건너뛰고 2번째 행부터 시작
    if cell:
        print(f"링크 {idx - 1}: {cell}")

        try:
            html_content = get_page_content(cell)
            if html_content:
                text_content = extract_content(html_content)
                if text_content:
                    print(f"본문 글자 수: {len(text_content)}")

                    # 글자 수가 100자 이상인지 확인하고 F열에 조건 통과 여부 표시
                    if len(text_content) >= 100:
                        result = '통과'
                    else:
                        result = '미통과'
                else:
                    result = '본문 없음'
            else:
                result = '링크 오류'
        except Exception as e:
            print(f"요청 오류: {e}")
            result = '링크 오류'

        # F열에 결과 업데이트
        worksheet.update_cell(idx, 6, result)
        print(f"F{idx}에 {result} 작성 완료!")

print("모든 작업 완료!")

 

GPT가 알려준 코드로 review.py를 수정하고 실행해보도록 하겠습니다.

 

↓구글시트 F열에 통과 여부 입력 됨

Visual Studio Code - Terminal에 출력된 결과값 (본문의 글자수도 확인 할 수 있습니다.)

 


만약 리뷰 링크에 로그인을 해야 본문이 확인 가능한 링크가 있을 경우는 아래코드를 이용바랍니다.

from oauth2client.service_account import ServiceAccountCredentials
import gspread
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
from bs4 import BeautifulSoup
import pickle
import os

# 구글 시트 API 사용을 위한 인증 정보 설정
scope = ['https://www.googleapis.com/auth/spreadsheets']
json_keyfile = r'키 파일 경로 입력'

creds = ServiceAccountCredentials.from_json_keyfile_name(json_keyfile, scope)
client = gspread.authorize(creds)

# 구글 시트 문서 가져오기
spreadsheet_url = '구글시트 URL 입력'
sheet = client.open_by_url(spreadsheet_url)

# 시트 이름으로 워크시트 선택
worksheet = sheet.worksheet('후기')

# E열의 링크 가져오기
column_e = worksheet.col_values(5)  # E열은 5번째 열

# 쿠키 저장 함수
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')
    options.add_argument('--ignore-ssl-errors')

    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 get_page_content_with_cookies(url, cookies_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')
    options.add_argument('--ignore-ssl-errors')

    driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
    
    try:
        driver.get(url)

        domain_key = "naver" if "naver.com" in url else "daum"

        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']
            cookie['domain'] = '.naver.com' if "naver.com" in url else '.daum.net'
            driver.add_cookie(cookie)

        driver.get(url)

        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, div.content.CafeViewer"))
        )
        
        html = driver.page_source
        return html

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

    finally:
        driver.quit()

# 본문 내용 추출
def extract_content(html):
    soup = BeautifulSoup(html, 'html.parser')
    content_div = soup.select_one('div.se-main-container, div.content.CafeViewer')
    
    if content_div:
        paragraphs = content_div.find_all('p')
        content_text = ''.join(p.get_text(strip=True) for p in paragraphs)
        return content_text
    else:
        return None

# 네이버 및 다음 로그인 후 쿠키 저장
naver_login_url = "https://nid.naver.com/nidlogin.login"
daum_login_url = "https://logins.daum.net/accounts/loginform.do"
cookies_file_path = "cookies.pkl"

save_cookies(naver_login_url, cookies_file_path, "naver")
save_cookies(daum_login_url, cookies_file_path, "daum")

# 결과 출력
print("E열 데이터:")

for idx, cell in enumerate(column_e[1:], start=2):
    if cell:
        print(f"링크 {idx - 1}: {cell}")

        try:
            html_content = get_page_content_with_cookies(cell, cookies_file_path)
            if html_content:
                text_content = extract_content(html_content)
                if text_content:
                    print(f"본문 글자 수: {len(text_content)}")

                    if len(text_content) >= 100:
                        result = '통과'
                    else:
                        result = '미통과'
                else:
                    result = '본문 없음'
            else:
                result = '링크 오류'
        except Exception as e:
            print(f"요청 오류: {e}")
            result = '링크 오류'

        worksheet.update_cell(idx, 6, result)
        print(f"F{idx}에 {result} 작성 완료!")

print("모든 작업 완료!")

 

이전 글에서 했던 것처럼 로그인 후 Terminal에서 Enter를 눌러 진행하시면 됩니다.


여기까지 진행하셨다면 이제 리뷰 확인하는 척 프로그램을 돌려두고 월급루팡을 진행하시면 됩니다!
지금까지 읽어주셔서 감사합니다.   (`Д´)ゞ

 

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

- amos1592@naver.com