AI SCHOOL/Python

[Python] 네이버 금융 뉴스기사 수집

moru_xz 2023. 1. 15. 23:21

목표 : pandas 의 read_html 을 통해서 테이블 형태의 표를 수집하는 방법을 알아봅니다.

1. 개별 종목에 대한 뉴스 기사를 수집합니다.
2. 한 페이지만 수집
3. 여러 페이지를 수집해서 하나로 병합합니다.
4파일형태로 저장합니다.

 

import pandas as pd

url_1 = 'https://finance.naver.com/item/news.naver?code=005930'

temp_table = pd.read_html(url_1, encoding="cp949")
temp_table[1]

우선 네이버 금융 뉴스 기사 url 을 불러온 뒤 pd.read_html을 통해 데이터 프레임으로 불러온다

 

pd.read_html로 확인할 수 있다는 것을 확인하고 제대로 스크랩핑을 한다

 

수집하려는 곳을 클릭하여 

검사 -> 네트워크 -> x표시 -> 페이지 넘기기 -> 뉴스의 request url 가져오기

 

url = 'https://finance.naver.com/item/news_news.naver?code=005930&page=3&sm=title_entity_id.basic&clusterId='

item_code = "035720"
item_name = "카카오"
page_no = 2

for page_no in range(1,3) :
    url = f'https://finance.naver.com/item/news_news.naver?code={item_code}&page={page_no}'
    print(url)

카카오라는 종목의 뉴스를 가져온다

for 문을 활용해서 원하는 분량(페이지)를 반복문을 통해 가져온다

 

table = pd.read_html(url, encoding= 'cp949')
table

table[0]

이 부분이 뉴스가 들어있는 칼럼이다

table[:-1]

이 부분이 페이징 페이지를 제외한 부분

 

하지만

table[0]은 Index(['제목', '정보제공', '날짜'], dtype='object') 인데,  table[1]은 Int64Index([0, 1, 2], dtype='int64') 이다.

table[:-1]까지 모든 데이터프레임의 칼럼을 '제목', '정보제공', '날짜'로 바꿔줘야 한다.

-> for문을 활용한다 

 

news_list = []
for news in table[:-1] : #페이징 테이블 말고 다 가져옴 
    news.columns = cols
    print(news.columns)
    display(news) #[0, 1, 2]로 되어있는 컬럼명 다 바꿔줌 
    news_list.append(news) # 담아줌줌

news_list[1] #지금은 다 따로 있음

하지만 append로 news_list에는 담겼지만 다 따로따로임

-> concat으로 합쳐줘야 함

그리고 결측치와 중복을 제거해야함

df_one_page = pd.concat(news_list)
df = df_one_page.dropna() #결측치 제거
df = df.drop_duplicates() #중복 제거

연관기사를 삭제한다

df = df[~df['제목'].str.contains('연관기사')]

 

이 모든 과정을 하나의 함수로 만든다 

우선 url 을 반환하는 함수 

def get_url(item_code,page_no):
    url = f'https://finance.naver.com/item/news_news.naver?code={item_code}&page={page_no}'
    return(url)

뉴스 페이지 수집 함수

def get_one_page_news(item_code, page_no):
    """
    get_url 에 item_code, page_no 를 넘겨 url 을 받아오고
    뉴스 한 페이지를 수집하는 함수
    1) URL 을 받아옴
    2) read_html 로 테이블 정보를 받아옴
    3) 데이터프레임 컬럼명을 ["제목", "정보제공", "날짜"]로 변경
    4) tmp_list 에 데이터프레임을 추가
    5) concat 으로 리스트 병합하여 하나의 데이터프레임으로 만들기
    6) 결측치 제거
    7) 연관기사 제거
    8) 중복데이터 제거
    9) 데이터프레임 반환
    """
    url = get_url(item_code,page_no)
    table = pd.read_html(url, encoding= 'cp949')
    table_list = []
    for i in table[:-1] :
        cols = table[0].columns
        i.columns = cols
        table_list.append(i)
    news = pd.concat(table_list)
    news = news.dropna()
    news = news[~news['제목'].str.contains('연관기사')]
    news = news.drop_duplicates()
    return news
get_one_page_news('005930', 1)

원하는 페이지까지 수집

반복문을 사용해서 10페이지까지 수집

import time
from tqdm import tqdm, trange
# 진행 상황 보는 

page_no = 10
news_list = []

for no in trange(1, page_no + 1) : #tqdm(range())와 같음
	df_one_news = get_one_page_news(itedm_code, no)
    news_list.append(df_one_news)
    time.sleep(0.2)
    
len(news_list)

news_list

df_news = pd.concat(news_list)
df_news.head(20)

 

# 수집한 페이지마다 인덱스가 0부터 시작을 하는데 
# 전체 인덱스를 다시 부여하고자 할 때 .reset_index(drop=True) 를 사용할 수 있습니다.
# reset_index() 에서 drop=True 를 사용하면 기존 인덱스는 제거합니다.

df_news = pd.concat(news_list)
df_news = df_news.reset_index(drop = True)
df_news.head(20)

# 파일로 저장하기
file_name = f"news_{item_code}_{item_name}.csv"
df_news.to_csv(file_name, index=False)
pd.read_csv(file_name)