RSS를 이용한 간단 뉴스 크롤링 시스템!

차보경·2022년 7월 13일
1

TIL

목록 보기
6/37
post-thumbnail

지난번 물류시스템 구축에 이어 오늘은 1시간 안에 뉴스 크롤링? 뉴스 요약시스템? 을 만들어 봤다!

이번에도 Good code, Bad code를 생각하며 실습 시작!

아래는 퍼실님이 제시한 상황! (항상 감사합니다 ㅈㅅ퍼실님!)
혹시 보시는 분이 계시다면 같이 해보셔도 재밌습니당:)!

🕺시스템 요구사항 명세서

💡 상황
고객A는 매일 아침 구글 뉴스를 보며 하루를 시작한다.
A씨는 매번 뉴스를 찾는 수고를 덜고싶어, 오늘의 뉴스와 뉴스를 검색하는 기능이 있는 뉴스 요약 시스템을 발주했다. 의뢰를 받은 당신은 해당 System을 CLI으로 구현하여 납품해야 한다.

💡 Feedparser - Python에서 RSS 데이터를 처리할 수 있는 라이브러리
라이브러리 설치 : pip install feedparser
라이브러리 사용 : import feedparser


1. 중앙 시스템

오늘의 뉴스(Today New), 키워드기반 뉴스 검색, 시스템 종료 기능에 접근할 수 있는 메인 시스템을 CLI으로 구현할 것.

필수 기능

  • 무한 반복문으로 주요 기능을 수행하도록 구성되어야 한다.
  • 주요 기능에 접근할 수 있어야 한다.
  • 유저가 입력할 수 있는 커맨드 인터페이스를 제공해야 한다.
  • 유저가 시스템에서 제공하는 번호와 다른 번호를 눌렀을 때 예외처리를 수행한다.
  • 유저가 입력한 기능은 int 정수형으로 처리해야한다.

2. 오늘의 뉴스 출력 시스템

뉴스 사이트에서 제공하는 오늘의 뉴스 데이터를 RSS로 조회 후, 출력하는 시스템을 CLI으로 구현할 것.

필수 기능

  • 구글 뉴스에서 제공하는 데이터를 RSS으로 조회한다.
  • 뉴스의 이름, 링크를 추출하여 6개 이상의 뉴스를 사용자에게 출력해야한다.
  • 데이터 출력 시, 각 뉴스별 1칸씩 개행처리를 수행해야한다.
  • 작업 완료 후, 메인 시스템으로 복귀해야한다.

3. 뉴스 검색 시스템

사용자가 입력한 키워드로 검색한 뉴스 데이터를 RSS로 조회 후, 출력하는 시스템을 CLI으로 구현할 것.

필수 기능

  • 사용자에게 검색 키워드를 입력받고 RSS Query에 적용해야한다.
  • 구글 뉴스에서 제공하는 데이터를 RSS으로 조회한다.
  • 뉴스의 이름, 링크를 추출하여 6개 이상의 뉴스를 사용자에게 출력해야한다.
  • 데이터 출력 시, 각 뉴스별 1칸씩 개행처리를 수행해야한다.
  • 작업 완료 후, 메인 시스템으로 복귀해야한다.

4. 뉴스 시스템 종료

메인 시스템의 동작을 종료하는 기능을 CLI으로 구현할 것.

필수 기능

  • 시스템 종료

구현 결과

1. 중앙 시스템

  • 커멘드 인터페이스를 제공
  • 제공하는 숫자가 아니면 예외처리
  • 개인적 추가)) int가 아닌 input의 예외처리

2. 오늘의 뉴스 출력 시스템

  • 구글 뉴스에서 제공하는 데이터를 RSS으로 조회 후 제목, 링크 출력 확인
  • (출력 여부를 알기위해 뉴스 출력 숫자는 2로 줄임)

3. 뉴스 검색 시스템

  • 검색어를 입력받고 RSS Query에 적용하여 출력 후 메인으로 돌아감 (제임스웹 사진 최고...d)

  • 검색 후 해당 뉴스가 없는 경우 예외처리 -> 다시 입력하게함

4. 뉴스 시스템 종료


실습 후 배운점

  1. 까먹지 말자 (좋은 코드 지향)
  • VS code에서 pip 설치시, new terminal 열어서 설치 후 import 진행!
  • 주석보다는 서술형 코드쓰기 (코드로 말하자)
  • 중복 코드는 함수로 묶어서 불러쓰기
  • 하드 코딩하지 말기 (유지보수를 위해선 잘 써야할 것 같다)
url_normal = ('https://news.google.com/rss?hl=ko&gl=KR&ceid=KR:ko')
news_data = feedparser.parse(url_normal)
########## 수정 코드 ###########
news_data = feedparser.parse('https://news.google.com/rss?hl=ko&gl=KR&ceid=KR:ko')
  1. 예외처리의 중요성!
  • 와... 이 몇가지 안되는 시스템에서도 예외 상황이 이만저만이 아니었다...! 여기저기 펑펑퍼버펑... 실제 상황이었다면 큰일이었을 것이다. 앞으로도 예외처리하는 것을 생활화하자! try - except 사랑해여...S2...
  1. 최대한 중복 줄이기
  • num_news, news_data, print_news 는 오늘의 뉴스나 키워드 뉴스 동일하게 사용하는 부분이다. 이걸 __init__으로 넣고 함수화함으로 확실히 짧아지고 간결해진 것을 느꼈다. 앞으로도 추상화로 중복 없이 간결한 코드를 짜도록 노력하자!
  1. 후에 주어질 값을 미리 함수에 사용한다면 함수 내에서 not defined로 에러가 난다. 그땐 def 함수명(self, 변수명)으로 주어질 값을 미리 넣어주면 됨

참고 블로그


작성 코드

import feedparser

class NewsSystem():
    def __init__(self):
        self.num_news = 2
        self.news_data = None

    def print_news(self):
        try: 
            for i in range(self.num_news):
                news = self.news_data.entries[i]
                print("제목 : ", news.title)
                print("링크 : ", news.link,'\n')
        except:
            print('해당 키워드의 뉴스가 없습니다. 다시 입력해주세요!')
            return self.topic_news()

    def today_news(self):
        self.news_data = feedparser.parse('https://news.google.com/rss?hl=ko&gl=KR&ceid=KR:ko')
        self.print_news(self.news_data)

    def topic_news(self):
        topic = str(input('뉴스 키워드를 입력해주세요 : '))
        self.news_data = feedparser.parse(f'https://news.google.com/rss/search?q={topic}&hl=ko&gl=KR&ceid=KR%3Ako')
        self.print_news(self.news_data)

    def shutdown(self):
        print('시스템을 종료합니다.')
        return exit()



def print_main_message():
        print('\n','==' * 20)
        print('뉴스 요약 메인 시스템에 접속하셨습니다:)!')
        print('[1] 오늘의 주요 뉴스 [2] 키워드 검색 [3] 시스템 종료')


def main():
    news_manager = NewsSystem()

    while(1):
        print_main_message()
        try: 
            select_num = int(input("실행 번호 : "))
        except:
            print('숫자를 입력해주세요!')
            continue

        if (select_num == 1):
            news_manager.today_news()
        elif (select_num == 2):
            news_manager.topic_news()
        elif (select_num ==3):
            news_manager.shutdown()
        else:
            print('상기 숫자를 입력해주세요:)! ')
            continue


if __name__ == "__main__":
	main()
profile
차보의 Data Engineer 도전기♥ (근데 기록을 곁들인)

0개의 댓글