본문 바로가기

Python/▶ Python & Pandas

TIL ②일차

728x90

Pandas - pd.read_html을 통해서 테이블 형태의 표를 수집

1) 검색 값 설정 

 

● (pd.read_html( )의 기능):

url, html 소스코드 넣어주면 페이지의 테이블 태그를 읽고 가져와서 리스트 형태로 반환

반환 된 리스트 인덱싱하면 데이터프레임형태

 

더보기
# 1) URL, HTML 소스코드를 넣어주게 되면 테이블 태그를 찾아서 반환합니다.
 
# 2) URL 을 넣어주면 특정 URL 에 접근해서 HTML 페이지의 table 태그를 읽어옵니다.
 
# 3) HTML 페이지의 table 태그는 <table></table> 로 구성이 됩니다.
 
# 4) 해당 HTML 의 모든 table을 가져와서 리스트 형태로 반환됩니다.
 
# 5) 반횐된 리스트를 인덱싱하게 되면 데이터프레임으로 되어 있습니다.

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

temp_table = pd.read_html(url, encoding='cp949')
len(temp_table)
-------------------------------------------------------------
9

 

#인덱싱하여 데이터프레임 형태로 보기

 

temp_table[7]

 

# 웹스크래핑은 리버스엔지니어링과 유사합니다. 

 

# 어떤 방식으로 웹페이지가 구성되어있는지를 알아야지 해당 웹페이지를 수집할 수 있습니다.
 

2) 뉴스페이지 가져오기 :

for 문 사용하여 url의 item_code & page_no 변경하여

원하는 종목의, 원하는 페이지 수 만큼의 뉴스 가져오기

 

더보기
# 수집할 url을 가져옵니다.
 
# item_code = "005930"
# item_name = "삼성전자"
 
item_code = '035720'
item_name = '카카오'
page_no = 1


# url
for page_no in range(1, 6):
    url = f'https://finance.naver.com/item/news_news.nhn?code={item_code}&page={page_no}'
    print(url)
------------------------------------------------------------------------------------------
https://finance.naver.com/item/news_news.nhn?code=035720&page=1
https://finance.naver.com/item/news_news.nhn?code=035720&page=2
https://finance.naver.com/item/news_news.nhn?code=035720&page=3
https://finance.naver.com/item/news_news.nhn?code=035720&page=4
https://finance.naver.com/item/news_news.nhn?code=035720&page=5

 

3) read_html로 수집하기

  • 네이버 금융의 주가 기사를 read_html로 수집해서 table 이라는 변수에 담습니다.
더보기
# 수집결과 는 table이라는 변수에 담아주세요.
# table
 
table = pd.read_html(url)
table

 

 

4) 데이터프레임으로 만들기

  • 위에서 수집한 결과 중 table 변수 안에 있는 0번째 인덱스 값을 가져와서 df 라는 변수에 담아주세요.

 

더보기
# table의 0번째 인덱스 값을 df 라는 변수에 담습니다.
# df
 
df = table[0]
df

 

5)  반복문으로 데이터 가져오기 +의문점 포함

 

  • for 문을 사용해 table 이라는 변수 안에 있는 값을 모두 가져오기
  • temp_list 에 수집한 값을 담기
더보기

가져온 read_html(url) 데이터 ( 테이블 태그들의 리스트 형태) 의

0번 인덱스 열들을 보면 이미 [0, 1, 2] 가 아닌 ['제목', '정보제공', '날짜']로 되어있는데 왜 바꿔주는거지..?

cols = table[0].columns
cols
------------------------
Index(['제목', '정보제공', '날짜'], dtype='object')
 
# table[:-1] => 맨 마지막 데이터프레임은 페이징 테이블이기 때문에 제외하고 가져옵니다.
# [0, 1, 2]로 되어있는 컬럼명을 ['제목', '정보제공', '날짜']로 변경해 주기위해
# 데이터프레임을 하나씩 불러와서 컬럼명을 변경
 
temp_list = []
for news in table[:-1]:
    news.columns = cols
    temp_list.append(news)
    display(news)
# for news in table:

 

6)  수집한 데이터 하나의 데이터프레임으로 합치기 

    ●pd.concat() : 기존에 존재하는 데이터를 merge 하는 기능

    ●concat :

      -axis=0 행을 기준으로 위아래로 같은 컬럼끼리 값을 이어 붙여 새로운 행을 만듦

      -axis=1 컬럼을 기준으로 인덱스가 같은 값을 옆으로 붙여 새로운 컬럼을 만듦

더보기
# pd.concat
df_one_page = pd.concat(temp_list)
df_one_page

 

7)  수집한 데이터의 결측치 제거

●.dropna( ) : 행이나 열 중에서 결측치가 들어있는 행,열 모두 제거

- axis 행,열 중에 무엇을 기준으로 삭제할 것인지

- axis : {0 or 'index', 1 or 'columns'}, default 0

- 기본적으로 dropna() 는,  모든 컬럼 데이터 중 하나라도 빠진 데이터가 있다면, 그 행을 삭제해버립니다.

[출처] 판다스 빈값(NA) 정리하기 feat. fillna(), dropna()|작성자 데이터공방

 

더보기
# shape를 출력했을 때 열의 수는 같고 행만 다르다.
# 행은 뉴스기사 분량에 따라 다르게 나옴
# dropna
df_one_page.shape
df = df_one_page.dropna()
df.shape
-------------------------
(13, 3)

 

8)  네이버 수집한 기사에서 '제목'에  '연관기사'가 들어가는 데이터 제거

●.str.contains( ) : 문자열 메서 드이며, 지정한 문자열 포함되어있는지 확인 가능

 - 를 사용하며 조건의 반대에는 앞에 ~ 표시로 표현할 수 있습니다.

더보기
pd.Series([True, False])
------------------------
0     True
1    False
dtype: bool


~pd.Series([True, False])
-------------------------
0    False
1     True
dtype: bool
~(df['제목'].str.contains('연관기사'))

 

9) 위 과정 함수로 제작

  • 빈칸을 완성해 수집한 table 을 넘겨주면 데이터프레임을 반환하는 함수를 완성해 주세요.
더보기
# get_url item_code, page_no 를 넘기면 url 을 반환하는 함수
def get_url(item_code, page_no):
    """
    item_code, page_no 를 넘기면 url 을 반환하는 함수
    """
    url = f'https://finance.naver.com/item/news_news.nhn?code={item_code}&page={page_no}'
    
    return url
get_url('035720',1)
------------------------------------------------------------------------------------------
'https://finance.naver.com/item/news_news.nhn?code=035720&page=1'

 

10) 뉴스 한 페이지를 수집하는 함수

 

더보기

   1) URL 을 받아옴
    2) read_html 로 테이블 정보를 받아옴
    3) 데이터프레임 컬럼명을 ["제목", "정보제공", "날짜"]로 변경
    4) temp_list 에 데이터프레임을 추가
    5) concat 으로 리스트 병합하여 하나의 데이터프레임으로 만들기
    6) 결측치 제거
    7) 연관기사 제거
    8) 중복데이터 제거
    9) 데이터프레임 반환

 

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

 

10-1) 뉴스 한 페이지를 수집하는 함수( 잘 나오는지 확인 )

 

더보기
page_no = 7

temp = get_one_page_news(item_code, page_no)
temp

 

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

  • 위에서 만든 함수를 활용합니다.
  • time.sleep() 을 통해 데이터를 쉬었다 가져오기

●trange : for문의 range 함수 자리에 쓰이며, for문의 반복과정을 %및 그래프로 표시

 

더보기
import time
from tqdm import trange

page_no = 10
item_code = '005930' #삼성전자
news_list = []

for i in trange(1, page_no + 1):
    news_list.append(get_one_page_news(item_code, page_no))
    #수집 대상 서버의 부담을 줄이기 위해 쉬었다가 가져옵니다.
    time.sleep(1)
    
display(news_list)
-----------------------------------------------------------

 

12) news_list에 담겨있는 뉴스페이지들

-> 판다스 활용해서 하나의 데이터프레임으로

 

더보기
# 수집한 페이지마다 인덱스가지고 있으므로 모든 페이지가 0부터 시작
#  따라서, 전체 인덱스를 다시 부여하고자 할 때 .reset_index(drop = True)를 사용할 수 있습니다.
# reset_index( ) 에서 drop = True 를 사용하면 기존 인덱스는 제거합니다.
df_news_list = pd.concat(news_list)
df_news_list = df_news_list.reset_index(drop + True)
df_news_list.tail()

 

13) 파일로 저장하기

더보기
file_name = f"news_{item_code}_{item_name}.csv"
file_name
 
# to_csv : 파일 저장하기
df.to_csv(f"news_{item_code}_{item_name}.csv", index = False)
 
# read_csv : 파일 읽어오기
 
 
pd.read_csv(f"news_{item_code}_{item_name}.csv")
728x90

'Python > ▶ Python & Pandas' 카테고리의 다른 글

5주차 plotly  (1) 2023.02.05
5주차 TIL ( Pandas : 시각화 )  (0) 2023.01.31
4주차 WIL  (1) 2023.01.19
TIL ①-2일차  (0) 2023.01.10
TIL ①일차  (0) 2023.01.09