본문 바로가기
코드리뷰/chatGPT(Python)코드

비트코인 헤드라인 뉴스 사이트 자동으로 만들기

by 디마드 2025. 1. 11.
반응형

암호화 화폐를 다루는 미디어 사이트에 접속해 주요 헤드라인 뉴스를 추출해 나만의 뉴스 사이트를 만들어 보자. 

1. 뉴스 원천은 어디? 

블록미디어 최신 뉴스를 사용한다.  (https://www.blockmedia.co.kr/)

코인 최신 뉴스

2. 기사 스크래핑은 누가?

인공지능을 이용한다. Claude로 시작해 ChatGpt로 마무리했다. 무료로 사용하다 보니 사용 제한이 걸렸기 때문이다. 

3. 코드 작성을 위한 사이트 분석

Claude에 블로미디어 url을 입력하고 뉴스기사 스크래핑을 요청했는데 결과가 제대로 나오지 않았다. 그래서 최신 기사가 있는 웹 페이지 위치를 알려주었다.  여기 copy element 소스를 Claude에 입력하고 기사 스크래핑을 했다. 

4. 스크래핑 소스코드 작성해줘.

claude는 다음 기능을 주요하게 구현하며 깔끔한 결과를 도출했다. 

  1. 웹사이트에서 최신 뉴스 기사를 스크래핑
  2. 제목, 링크, 날짜 정보를 추출
  3. 데이터를 DataFrame으로 변환
  4. CSV 파일로 저장
import requests
from bs4 import BeautifulSoup
import pandas as pd
from datetime import datetime
import time

def scrape_blockmedia():
    # 기본 URL 설정
    url = "https://www.blockmedia.co.kr/"
    
    try:
        # User-Agent 설정
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }
        
        # 웹페이지 요청
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        response.encoding = 'utf-8'
        
        # BeautifulSoup 객체 생성
        soup = BeautifulSoup(response.text, 'html.parser')
        
        # 뉴스 기사 컨테이너 찾기
        news_items = []
        articles = soup.find_all('article', class_='l-post')
        
        for article in articles:
            try:
                # 날짜 추출
                date_element = article.find('time', class_='post-date')
                date = date_element.text.strip() if date_element else "날짜 없음"
                
                # 제목과 링크 추출
                title_element = article.find('h2', class_='post-title')
                title_link = title_element.find('a') if title_element else None
                
                title = title_link.text.strip() if title_link else "제목 없음"
                link = title_link['href'] if title_link else ""
                
                # 이미지 URL 추출
                img_element = article.find('span', class_='img')
                image_url = img_element.get('data-bgsrc', '') if img_element else ""
                
                news_items.append({
                    'title': title,
                    'link': link,
                    'date': date,
                    'image_url': image_url,
                    'scraped_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                })
            except Exception as e:
                print(f"기사 파싱 중 에러 발생: {str(e)}")
                continue
        
        # DataFrame 생성
        df = pd.DataFrame(news_items)
        
        # CSV 파일로 저장
        filename = f"blockmedia_news_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
        df.to_csv(filename, index=False, encoding='utf-8-sig')
        
        print(f"스크래핑 완료: {len(news_items)}개의 기사가 {filename}에 저장되었습니다.")
        return df
        
    except requests.exceptions.RequestException as e:
        print(f"웹사이트 접속 중 에러 발생: {str(e)}")
        return None
    except Exception as e:
        print(f"예상치 못한 에러 발생: {str(e)}")
        return None

if __name__ == "__main__":
    # 실행
    df = scrape_blockmedia()
    
    if df is not None:
        # 결과 출력
        print("\n최근 뉴스 목록:")
        for idx, row in df.iterrows():
            print(f"\n[{row['date']}] {row['title']}")
            print(f"링크: {row['link']}")

최신 뉴스 자동 추출 결과

5. 출력결과를 웹 페이지로 만들기

추출된 헤드라인 뉴스만 html과 css를 이용해 파일로 출력하는 코드를 작성해 줘

chatgpt에 이전 코드를 올려 작업하게 했다. html과 css를 적절하게 구성해 깔끔한 뉴스 매거진을 만들었다. 

import requests
from bs4 import BeautifulSoup
from datetime import datetime

def create_news_html():
    # CSS 스타일을 별도의 문자열로 정의
    css_style = """
    body {
        font-family: 'Arial', sans-serif;
        margin: 0;
        padding: 20px;
        background-color: #f5f5f5;
    }
    .container {
        max-width: 1200px;
        margin: 0 auto;
        background-color: white;
        padding: 20px;
        border-radius: 10px;
        box-shadow: 0 0 10px rgba(0,0,0,0.1);
    }
    .header {
        background-color: #2c3e50;
        color: white;
        padding: 20px;
        border-radius: 8px;
        margin-bottom: 20px;
    }
    .header h1 {
        margin: 0;
        font-size: 24px;
    }
    .news-list {
        list-style: none;
        padding: 0;
    }
    .news-item {
        background-color: white;
        border: 1px solid #e0e0e0;
        border-radius: 8px;
        margin-bottom: 15px;
        padding: 15px;
        transition: transform 0.2s ease;
    }
    .news-item:hover {
        transform: translateX(10px);
    }
    .news-link {
        text-decoration: none;
        color: #2c3e50;
        display: block;
    }
    .news-title {
        font-size: 18px;
        font-weight: bold;
        margin-bottom: 8px;
    }
    .news-date {
        font-size: 14px;
        color: #666;
    }
    .news-meta {
        display: flex;
        justify-content: space-between;
        align-items: center;
    }
    .news-image {
        width: 200px;
        height: 120px;
        object-fit: cover;
        border-radius: 4px;
        margin-left: 15px;
    }
    .generated-time {
        text-align: center;
        color: #666;
        font-size: 14px;
        margin-top: 20px;
        padding-top: 20px;
        border-top: 1px solid #e0e0e0;
    }
    """

    # HTML 템플릿
    html_template = f"""
    <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>블록미디어 헤드라인 뉴스</title>
        <style>
        {css_style}
        </style>
    </head>
    <body>
        <div class="container">
            <div class="header">
                <h1>블록미디어 헤드라인 뉴스</h1>
            </div>
            <ul class="news-list">
                {{news_items}}
            </ul>
            <div class="generated-time">
                생성 시간: {{generated_time}}
            </div>
        </div>
    </body>
    </html>
    """
    
    try:
        # 웹사이트 접속
        url = "https://www.blockmedia.co.kr/"
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }
        
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        
        soup = BeautifulSoup(response.text, 'html.parser')
        news_items = []
        
        # 뉴스 기사 찾기
        articles = soup.find_all('article', class_='l-post')
        
        for article in articles:
            try:
                # 날짜 추출
                date_element = article.find('time', class_='post-date')
                date = date_element.text.strip() if date_element else "날짜 없음"
                
                # 제목과 링크 추출
                title_element = article.find('h2', class_='post-title')
                title_link = title_element.find('a') if title_element else None
                
                if title_link:
                    title = title_link.text.strip()
                    link = title_link['href']
                    
                    # 이미지 URL 추출
                    img_element = article.find('span', class_='img')
                    image_url = img_element.get('data-bgsrc', '') if img_element else ""
                    
                    # 뉴스 아이템 HTML 생성
                    news_item_html = f"""
                    <li class="news-item">
                        <a href="{link}" class="news-link" target="_blank">
                            <div class="news-meta">
                                <div>
                                    <div class="news-title">{title}</div>
                                    <div class="news-date">{date}</div>
                                </div>
                                <img src="{image_url}" alt="{title}" class="news-image" onerror="this.style.display='none'">
                            </div>
                        </a>
                    </li>
                    """
                    news_items.append(news_item_html)
            
            except Exception as e:
                print(f"기사 파싱 중 에러 발생: {str(e)}")
                continue
        
        # 현재 시간 포맷팅
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        # 최종 HTML 생성
        # final_html = html_template.format(
        #     news_items="\n".join(news_items),
        #     generated_time=current_time
        # )

        # 최종 HTML 생성
        final_html = html_template.replace("{news_items}", "\n".join(news_items)).replace("{generated_time}", current_time)

        # 파일로 저장
        filename = f"blockmedia_news_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html"
        with open(filename, 'w', encoding='utf-8') as f:
            f.write(final_html)
            
        print(f"HTML 파일이 생성되었습니다: {filename}")
        
    except requests.exceptions.RequestException as e:
        print(f"웹사이트 접속 중 에러 발생: {str(e)}")
    except Exception as e:
        print(f"에러 발생: {str(e)}")

if __name__ == "__main__":
    create_news_html()

chatgpt 최신 뉴스 헤드라인 메거진 만들기

6. 마치며

헤드라인 뉴스 메거진 소스코드는 모두 인공지능이 담당했다. 에러 디버깅 포함해서다. 프로그래머가 아니더라도 이젠 생성형 인공지능을 이용하면 충분히 개발이 가능하다는 얘기다. 물론, 프로그램 기초가 있다면 더할 나위 없기는 하다. 

 

7. 부록 : 효율적인 프롬프트

코드의 주요 기능:

  1. 웹사이트에서 최신 뉴스 기사를 스크래핑
  2. 제목, 링크, 날짜 정보를 추출
  3. 데이터를 DataFrame으로 변환
  4. CSV 파일로 저장
  5. 이미지 URL 추출 ('data-bgsrc' 속성 사용)
  6. 더 자세한 에러 메시지 출력
  7. 결과 출력 형식 개선

이 코드를 실행하면 블록미디어의 최신 뉴스 기사들을 스크래핑하여 CSV 파일로 저장하고, 콘솔에 결과를 출력합

웹 페이지 만들기 프롬프트

프런트엔드 (HTML/CSS/JavaScript):

  • 모던한 카드 기반 뉴스 레이아웃
  • 반응형 디자인
  • 뉴스 카드 호버 효과
  • 이미지, 제목, 요약, 날짜 표시
  • 클릭 시 원본 기사로 이동

전체 요약

 

  • 뉴스 스크래핑:
    • 블록미디어 웹사이트에서 최신 뉴스 추출
    • 제목, 링크, 날짜, 이미지 URL 수집
  • HTML 생성:
    • 반응형 디자인
    • 깔끔한 카드 스타일 레이아웃
    • 호버 효과
    • 이미지 표시 (이미지 로드 실패 시 자동으로 숨김)
  • 스타일링:
    • 모던한 디자인
    • 그림자 효과
    • 부드러운 애니메이션
    • 읽기 좋은 타이포그래피
  • 파일 저장:
    • 타임스탬프가 포함된 파일명으로 저장
    • UTF-8 인코딩 사용

 

반응형

댓글