네이버 최신 뉴스 헤드라인을 추출해 보자.
일반적으로 웹 데이터를 추출하는 것을 웹크롤링이라 한다. 주로 파이썬을 이용해 웹 페이지 분석 후 필요한 데이터를 가져오는 코드를 작성하는데, 웹 페이지 소스코드 분석과 파이썬 크롤링 코드 작성이란 쉽지 않은 관문이 있다. 물론 웹 개발 경험이 있다면 쉽게 코드를 구현할 수 있겠지만 그렇지 않을 경우는 자동화 코드를 만들기 쉽지 않다.
이런 어렵고 복잡한 부분은 인공지능에게 작업하게 하고 우리는 그 결과에 피드백을 제공하면 원하는 결과물을 얻을 수 있지 않을까 생각한다. 인공지능과의 채팅은 누구든 할 수 있으니 말이다.
1. 어떤 데이터를 추출할 것인가?
네이버 뉴스 기사 웹 페이지에 접속해 URL 을 카피하자
> https://news.naver.com/section/104
2. 웹 페이지 정보 추출 지시 (claude)
https://news.naver.com/section/104 웹페이지에서 헤드라인 뉴스 5개 정보를 가져오는 소스를 작성해 줘. 파이썬으로 코드 작성하고 제목/내용/기사링크/이미지링크/출처를 추출해 줘
import requests
from bs4 import BeautifulSoup
import pandas as pd
from datetime import datetime
def get_naver_news_headlines():
# 네이버 뉴스 세계 섹션 URL
url = "https://news.naver.com/section/104"
# User-Agent 설정
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
try:
# 웹페이지 요청
response = requests.get(url, headers=headers)
response.raise_for_status() # 오류 체크
# BeautifulSoup으로 파싱
soup = BeautifulSoup(response.text, 'html.parser')
# 뉴스 항목들을 담을 리스트
news_items = []
# 메인 뉴스 컨테이너 찾기
news_list = soup.select('.newspaper_wrp')[:5] # 상위 5개 뉴스만 가져오기
for item in news_list:
try:
# 제목
title = item.select_one('.newspaper_text').get_text(strip=True)
# 내용 (서브텍스트)
content = item.select_one('.newspaper_subtext').get_text(strip=True) if item.select_one('.newspaper_subtext') else "내용 없음"
# 링크
link = "https://news.naver.com" + item.select_one('a')['href']
# 이미지 링크
img_tag = item.select_one('img')
image_link = img_tag['src'] if img_tag else "이미지 없음"
# 출처
source = item.select_one('.newspaper_item_source').get_text(strip=True) if item.select_one('.newspaper_item_source') else "출처 없음"
news_items.append({
'제목': title,
'내용': content,
'링크': link,
'이미지_링크': image_link,
'출처': source
})
except AttributeError as e:
print(f"파싱 오류 발생: {e}")
continue
# DataFrame 생성
df = pd.DataFrame(news_items)
# 결과 출력
print("\n=== 네이버 뉴스 헤드라인 ===")
for idx, row in df.iterrows():
print(f"\n[뉴스 {idx+1}]")
print(f"제목: {row['제목']}")
print(f"내용: {row['내용']}")
print(f"링크: {row['링크']}")
print(f"이미지: {row['이미지_링크']}")
print(f"출처: {row['출처']}")
print("-" * 50)
return df
except requests.RequestException as e:
print(f"요청 중 오류 발생: {e}")
return None
if __name__ == "__main__":
headlines_df = get_naver_news_headlines()
이 코드를 복사해 vscode에서 돌렸는데 뉴스 헤드라인을 전혀 가져오지 못했다. 아래 코드가 문제였다. 크롤링을 위한 대상 클래스에 엉뚱한 값이 들어가 있었다. 실제 뉴스기사 웹 페이지에는 newspaper_wrp 클래스가 없었다.
# 메인 뉴스 컨테이너 찾기
news_list = soup.select('.newspaper_wrp')[:5] # 상위 5개 뉴스만 가져오기
해결을 위해 좀 더 구체적인 소스를 지정해 주었다.
(1) 웹 페이지에서 F12 눌러 개발자 모드로 변경
(2) 헤드라인 뉴스 대상 선정
(3) 소스 카피 (copy element) 후 파일저장 (핵심)
(4) claude에 첨부파일을 올려 다시 작업지시 (핵심)
(5) claude가 만든 코드
HTML 문서를 분석해보니 실제 네이버 뉴스의 DOM 구조가 있네요. 이를 바탕으로 더 정확한 크롤링 코드를 작성해드리겠습니다.
```python
import requests
from bs4 import BeautifulSoup
import pandas as pd
from datetime import datetime
def get_naver_news_headlines():
# 네이버 뉴스 세계 섹션 URL
url = "https://news.naver.com/section/104"
# User-Agent 설정
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
try:
# 웹페이지 요청
response = requests.get(url, headers=headers)
response.raise_for_status()
# BeautifulSoup으로 파싱
soup = BeautifulSoup(response.text, 'html.parser')
# 뉴스 항목들을 담을 리스트
news_items = []
# 상위 5개 뉴스 항목 찾기
news_list = soup.select('li.sa_item')[:5]
for item in news_list:
try:
# 제목 추출
title = item.select_one('.sa_text_strong').get_text(strip=True)
# 내용 추출
content = item.select_one('.sa_text_lede').get_text(strip=True)
# 링크 추출 (href 속성)
link = item.select_one('.sa_text_title')['href']
# 이미지 링크 추출
img_tag = item.select_one('.sa_thumb img')
image_link = img_tag['src'] if img_tag else "이미지 없음"
# 출처 추출
source = item.select_one('.sa_text_press').get_text(strip=True)
news_items.append({
'제목': title,
'내용': content,
'링크': link,
'이미지_링크': image_link,
'출처': source
})
except AttributeError as e:
print(f"파싱 오류 발생: {e}")
continue
# DataFrame 생성
df = pd.DataFrame(news_items)
# 결과 출력
print("\n=== 네이버 뉴스 헤드라인 ===")
for idx, row in df.iterrows():
print(f"\n[뉴스 {idx+1}]")
print(f"제목: {row['제목']}")
print(f"내용: {row['내용']}")
print(f"링크: {row['링크']}")
print(f"이미지: {row['이미지_링크']}")
print(f"출처: {row['출처']}")
print("-" * 50)
return df
except requests.RequestException as e:
print(f"요청 중 오류 발생: {e}")
return None
if __name__ == "__main__":
headlines_df = get_naver_news_headlines()
```
주요 변경사항:
1. 실제 DOM 구조에 맞게 선택자 수정:
- 뉴스 항목: `li.sa_item`
- 제목: `.sa_text_strong`
- 내용: `.sa_text_lede`
- 링크: `.sa_text_title[href]`
- 이미지: `.sa_thumb img[src]`
- 출처: `.sa_text_press`
2. 에러 처리 강화:
- 각 항목별 예외처리
- 이미지가 없는 경우 처리
이 코드를 실행하면 네이버 뉴스 세계면의 상위 5개 헤드라인을 정확하게 추출할 수 있습니다. 필요한 수정사항이 있으시다면 말씀해 주세요!
(6) 작업 돌려보기
vs code에서 실행하니 이미지 링크 정보 추출 시 에러가 발생한다.
에러 디버깅해 줘. C:\Users\gus\Documents\dev\dockerLab> py news.py Traceback (most recent call last): File "C:\Users\gus\Documents\dev\dockerLab\news.py", line 80, in <module> headlines_df = get_naver_news_headlines() ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\gus\Documents\dev\dockerLab\news.py", line 42, in get_naver_news_headlines image_link = img_tag['src'] if img_tag else "이미지 없음" ~~~~~~~^^^^^^^ File "C:\Users\gus\Documents\dev\dockerLab\.venv\Lib\site-packages\bs4\element.py", line 1573, in getitem return self.attrs[key] ~~~~~~~~~~^^^^^ KeyError: 'src'
원인을 물어보니 이미지 정보가 지연로딩되기 때문에 가져오지 못했다는 거다.
이미지 태그의 속성 접근 부분에서 에러가 발생했네요. 실제 HTML을 보니 이미지가 지연 로딩(lazy loading)되는 구조라 'src' 대신 다른 속성을 사용하고 있습니다. 수정된 코드를 작성해 드리겠습니다.
가변적이거나 지연되는 경우 beautfiul soup을 이용해 데이터 추출이 어렵다. 그래서 다른 방법을 알려달라고 했더니 selenium을 추천한다.
BeautifulSoup만으로는 지연 로딩된 이미지의 실제 URL을 가져오기가 어렵습니다. 이는 JavaScript가 실행되어야 실제 이미지가 로드되기 때문입니다. 이를 해결하기 위해서는 두 가지 방법을 제안드립니다:
Selenium을 사용하는 방법:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import pandas as pd
from datetime import datetime
def get_naver_news_headlines():
# Chrome WebDriver 설정
options = webdriver.ChromeOptions()
options.add_argument('--headless') # 헤드리스 모드 실행
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
try:
# WebDriver 초기화
driver = webdriver.Chrome(options=options)
# 네이버 뉴스 세계 섹션 접속
driver.get("https://news.naver.com/section/104")
# 이미지가 로드될 때까지 대기 (최대 10초)
wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'img._LAZY_LOADING')))
# 뉴스 항목들을 담을 리스트
news_items = []
# 상위 5개 뉴스 항목 찾기
news_list = driver.find_elements(By.CSS_SELECTOR, 'li.sa_item:not(.is_blind)')[:5]
for item in news_list:
try:
# 제목 추출
title = item.find_element(By.CSS_SELECTOR, '.sa_text_strong').text
# 내용 추출
content = item.find_element(By.CSS_SELECTOR, '.sa_text_lede').text
# 링크 추출
link = item.find_element(By.CSS_SELECTOR, 'a.sa_text_title').get_attribute('href')
# 이미지 링크 추출
try:
img = item.find_element(By.CSS_SELECTOR, 'img._LAZY_LOADING')
image_link = img.get_attribute('src')
except:
image_link = "이미지 없음"
# 출처 추출
source = item.find_element(By.CSS_SELECTOR, '.sa_text_press').text
news_items.append({
'제목': title,
'내용': content,
'링크': link,
'이미지_링크': image_link,
'출처': source
})
except Exception as e:
print(f"파싱 오류 발생: {str(e)}")
continue
# WebDriver 종료
driver.quit()
# DataFrame 생성
df = pd.DataFrame(news_items)
# 결과 출력
print("\n=== 네이버 뉴스 헤드라인 ===")
for idx, row in df.iterrows():
print(f"\n[뉴스 {idx+1}]")
print(f"제목: {row['제목']}")
print(f"내용: {row['내용']}")
print(f"링크: {row['링크']}")
print(f"이미지: {row['이미지_링크']}")
print(f"출처: {row['출처']}")
print("-" * 50)
return df
except Exception as e:
print(f"오류 발생: {e}")
return None
finally:
try:
driver.quit()
except:
pass
if __name__ == "__main__":
headlines_df = get_naver_news_headlines()
JavaScript 렌더링 없이 이미지 URL을 추출하는 방법:
네이버 뉴스의 경우, 이미지 URL이 특정 패턴을 따르는 경우가 많습니다
기사 ID를 추출하여 이미지 URL을 구성할 수 있습니다
하지만 이 방법은 네이버의 URL 구조가 변경되면 작동하지 않을 수 있습니다
3. 인공지능에게 작업을 효율적으로 시키자.
이번 포스팅의 핵심은 크로링 대상 부분을 인공지능에게 알려줘 데이터를 추출하게 하는거다. 작업 범위가 명확해지고 작업 명령시 중복 오류도 최소화할 수 있다. 사용자는 인공지능과 작업 명령과 결과확인 그리고 수정요청을 계속해 원하는 결과물이 나올 때까지 반복하면 된다.
'코드리뷰 > chatGPT(Python)코드' 카테고리의 다른 글
뉴스 기사 추출하는 코드 만들어 줄래? 3탄 docker 결과 파일 가져오기 (2) | 2024.12.28 |
---|---|
코드 한 줄로 프로그램 배포하기 (0) | 2024.10.18 |
아이폰은 왜 잘 팔릴까? 심플한 UI 만들기 5단계 비법 공개 (2) | 2024.10.12 |
댓글