본문 바로가기
* 디지털 노마드/Python

네이버 종목게시판 크롤링

by lesrois 2020. 11. 14.

요즘 제일 재밌는 게,

네이버 종목게시판 구경하기다. 너무 웃겨 ㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

 

그래서 네이버 종목 게시판을 BeautifulSoup으로 크롤링해서, 

워드 클라우드까지 만들어 보기로 했다.

 

개발 환경은 구글 코랩(Colab)으로, 클라우드 기반의 무료 Jupyter 노트북 개발 환경이다.

 

 

 

1. 라이브러리 불러오기, 베이스 url 설정하기

 

먼저 필요한 라이브들을 불러들이고, 베이스가 되는 url을 설정한다.

import requests
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np
import re
import requests
from urllib.request import urlopen
import lxml.html
import time
import json
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import csv


base_url = 'https://finance.naver.com/item/board.nhn?code='

 

네이버 종목 게시판을 접속해보면 url이 종목 A코드가 들어가면서 변화하는 것을 알 수 있다.

 

 

 

여기서, 페이지까지 변화시키고자 한다면, "&page=2" 등을 붙여서 조건을 하나 더 줄 수 있다.

종목 토론실 페이지가 넘어가는 것을 확인할 수 있다.

 

 

2. 나눔고딕 폰트로 변환

 

 

추후 워드클라우드로 나타내기 위해서는, 나눔고딕 등 한글폰트로 바꾸어 주어야 한다.

아니면 그냥 네모 모양으로 깨져서 나타나게 된다..

아래는 시스템에 설정되어 있는 폰트를 확인하는 코드이다.

# 시스템에 설치된 폰트 확인
import matplotlib.font_manager as fm  # 폰트 관련 용도

sys_font=fm.findSystemFonts()
print(f"sys_font number: {len(sys_font)}")
print(sys_font)

 

만약 나눔고딕 폰트가 설치 되어 있지 않다면,

특히 코렙(Colab) 환경에서의 경우는 아래를 실행하면 된다.

 

# 나눔고딕 Install
!apt-get update -qq
!apt-get install fonts-nanum* -qq

 

아래 코드를 통해 체크해보면 전체 폰트와 나눔 폰트의 개수가 늘어나 있는 것을 확인해 볼 수 있다.

# 체크해보면 폰트 개수가 늘어났다
sys_font=fm.findSystemFonts()
print(f"sys_font number: {len(sys_font)}")

nanum_font = [f for f in sys_font if 'Nanum' in f]
print(f"nanum_font number: {len(nanum_font)}")

 

그렇다면 나눔 폰트의 경로는?

# 한번 프린트 해보자
nanum_font

위와 같이 프린트해서 경로를 얻을 수 있다.

 

 

3. 종목게시판 크롤링 코드 함수화

 

이제는 가장 핵심인 부분, 종목게시판을 크롤링 하는 코드이다.

일반적으로 그냥 request를 하게 되면 네이버에서 컴퓨터로 인식해서 데이터를 크롤링해 가져올 수가 없어서,

headers를 'User-Agent'로 지정하여 사람으로 인식하도록 하였다.

 

또, 종목별로 가져올 때마다 더 간편하게 가져 올 수 있도록 함수화 시켰다.

함수의 변수는 acode(종목코드), page(페이지)로 지정했다.

 

def naver_crawler(acode, page):
    headers = {'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3)'}
    total_dt = pd.DataFrame([])
    
    n_ = 0
    for page in range(1, page):
        
        n_ += 1
        if (n_ % 10 == 0):
            print('================== Page ' + str(page) + ' is done ==================')

        # url = "https://finance.naver.com/item/board.nhn?code=%s&page=%s" % (acode, page)
        url = "https://finance.naver.com/item/board.nhn?code=%s&page=%s" % (str(acode), str(page))

        result = requests.get(url, headers = headers)
        bs_obj = BeautifulSoup(result.content, "html.parser")
        table = bs_obj.find('table', {'class' : 'type2'})
        tt = table.select('tbody > tr')

        for i in range(2, len(tt)):
            if len(tt[i].select('td > span')) > 0:
              # print(i)
              date = tt[i].select('td > span')[0].text
              title = tt[i].select('td.title > a')[0]['title']
              writer = tt[i].select('td.p11')[0].text.replace('\t', '').replace('\n', '')
              views = tt[i].select('td > span')[1].text
              pos = tt[i].select('td > strong')[0].text
              neg = tt[i].select('td > strong')[1].text
              # print(date, title, writer, views, pos, neg)
              
              table = pd.DataFrame({'날짜' : [date], 
                                    '제목' : [title],
                                    '글쓴이' : [writer],
                                    '조회' : [views],
                                    '공감' : [pos],
                                    '비공감' : [neg]
                                    })
              total_dt = total_dt.append(table)
    
    return total_dt

 

4. 크롤링을 해보자!

 

올 하반기에 핫했던 빅히트(352820) 종목을 10페이지 정도 긁어와 보았다.

날짜/제목/글쓴이/조회/공감/비공감으로 정렬되는 것을 알 수 있다.

 

 

제목 컬럼에 있는 텍스트 데이터를 join 시켜 다 붙이면 이렇게 긴 string으로 나오게 된다.

 

 

 

5. 워드클라우드로 나타내기

 

워드클라우드는 워드클라우드 라이브러리로 정말 쉽게 만들 수 있다.

 

text =  ' '.join(data['제목'].tolist())

wc = WordCloud(font_path='/usr/share/fonts/truetype/nanum/NanumGothicEcoBold.ttf', 
               background_color = 'white', 
               width = 1000, height = 1000, max_words = 100, max_font_size = 300
               )
wc.generate(text)
plt.imshow(wc, interpolation = 'bilinear')
plt.axis("off")

 

다만 한글은 폰트때문에 깨지는 일이 자주 발생하는데,

폰트를 지정하지 않고 워드클라우드를 만들게 되면, 아래와 같이 네모모양으로 깨져서 나타난다.

 

 

하지만, 위의 나눔 폰트 경로 중 하나를 지정해서 나타나게 되면?

 

 

 

이렇게 네이버 종목 게시판을 크롤링 해서, 간단하게 워드 클라우드를 만들어 보았다.