본문 바로가기

코딩

파이썬 네이버 금융 업종 스크래핑

이제 마지막 스크래핑, 사실 이거 하려고 지금까지 연습했습니다. 촤하하

어떤 기업을 매매해야 할까? 아무리 기술적 매매를 한다고 해도 근본이 없는 주식은 사고 싶지가 않은 기분이다.

실제로 어떻게 매매하는지는 모르지만 그래도 업계에서 괜찮은 주식을 사거나 하고 싶은 기분?

그래서 네이버 금융에서 업종별 데이터를 얻어보려고 한다.

 

라이브러리부터 불러오자

import pandas as pd
import numpy as np
import requests
import lxml
from bs4 import BeautifulSoup
from requests import Response
import re

headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'}

눈치채셨는지는 모르겠지만, 이번에는 정규표현식을 사용하여 re 라이브러리도 추가되었습니다.

 

https://finance.naver.com/sise/sise_group.naver?type=upjong 

여기가 네이버 금융 업종 페이지인데, 업종별로 각각 페이지가 존재하고, 그 페이지에는 시가총액, 영업이익, PER 등의 정보가 각각 존재한다.

목표는 각 업종별로 저 정보들을 모두 모아서 하나의 데이터 구조 안에 저장하는 것이다.

 

 

개발자 도구를 열어 링크가 걸린 업종 이름을 보면 html 구조 내부에 해당 업종으로 이동하는 주소가 "tbody" 태그 아래의 "a" 태그에 들어있는 것을 확인할 수 있다.

각 주소를 확인해보면 모든 주소는 동일하고 "no="뒤의 업종 번호만 달라지면서 주소가 변하는 것도 확인할 수 있었다.

 

이 페이지에서 업종의 이름과 해당 업종의 번호를 얻어내면 될 것 같다.

 

<a href="/sise/sise_group_detail.naver?type=upjong&amp;no=290">교육서비스</a>

 

해당 링크 주소에서 필요한 것은 no뒤의 3자리 숫자와, 그 뒤에 오는 업종 이름이다.

 

 

'no=(.+?)">(.+?)</a>'

 

정규표현식 라이브러리를 이용하면 괄호 안의 정보를 빼낼 수 있다.

이것을 이용하여 아래의 코드로 업종의 정보를 얻어올 수 있다. 확인한 결과 번호가 3자리 미만인 경우도 있었는데, 앞을 0으로 채워 3자리를 맞춰주었다.

css 선택자에서 바로 하위 태그가 아닐 경우 "td a"처럼 띄워서 처리해주면 된다.

 

url_upjong = "https://finance.naver.com/sise/sise_group.naver?type=upjong"
res = requests.get(url_upjong, headers=headers)
page_soup = BeautifulSoup(res.text, "lxml")
summary_html = page_soup.select('td a')
upjong_list = pd.DataFrame(re.findall('no=(.+?)">(.+?)</a>',str(summary_html)))
upjong_list = upjong_list.rename(columns={0:"no",1:"upjong"}).sort_values(by=['upjong']).reset_index(drop=True)
upjong_list.no = upjong_list.no.str.zfill(3)

 

 

 

반응형

 

해당 업종 페이지로 이동해서 보면 여러 선택 옵션이 있다. 앞에서 한 것처럼 네트워크에서 옵션에 따라 요청하는 url을 확인해 주고, 각 주소별로 정보를 합쳐주기로 했다. 옵션이 한 번에 6개밖에 선택이 안 되어서 아래 박스 친 15개 옵션만 3번에 나눠서 가져오기로 했다. 필요하시면 더 넣어주시면 됩니다.

 

 

request_upjong_url = "https://finance.naver.com/sise/field_submit.naver?menu=upjong&returnUrl=http%3A%2F%2Ffinance.naver.com%2Fsise%2Fsise_group_detail.naver%3Ftype%3Dupjong%26no%3D"
request_url1 = "&fieldIds=market_sum&fieldIds=property_total&fieldIds=debt_total&fieldIds=sales&fieldIds=sales_increasing_rate"
request_url2 = "&fieldIds=operating_profit&fieldIds=operating_profit_increasing_rate&fieldIds=net_income&fieldIds=eps&fieldIds=dividend"
request_url3 = "&fieldIds=per&fieldIds=roe&fieldIds=roa&fieldIds=listed_stock_cnt&fieldIds=pbr&fieldIds=reserve_ratio"

 

맨 처음 url은 기본 주소이고, 뒤 3개의 request_url들은 각각 옵션 선택에 따라 달라지는 주소들이다.

 

upjong = pd.DataFrame()
for i in (upjong_list['no'].to_list()):
    temp = pd.DataFrame()
    for j in ([request_url1,request_url2,request_url3]):
        res = requests.get(request_upjong_url+i+j, headers=headers)
        page_soup = BeautifulSoup(res.text, "lxml")
        upjong_data_html = page_soup.select_one('#contentarea > div:nth-child(5)')
        col = [item.get_text().strip() for item in upjong_data_html.select('thead th')]
        col = [x for x in col if x not in ['종목명','토론실']]
        row = [item.get_text().strip() for item in upjong_data_html.select('tbody a')]
        row = list(filter(None,row))
        num = np.array([item.get_text().strip() for item in upjong_data_html.select('td.number')])
        num.resize(len(row),len(col))
        df = pd.DataFrame(num,columns=col,index=row).drop(columns=['현재가','전일비','등락률'])
        temp = pd.concat([temp,df], axis = 1)
    temp.index = pd.MultiIndex.from_product([[upjong_list[upjong_list.no==i].upjong.iat[0]],temp.index],names=["Sector","Stock"])
    upjong = pd.concat([upjong,temp], axis = 0)

 

이후 이전과 같이 먼저 빈 데이터프레임을 만들고, 주소를 업종별로, 그 아래에선 옵션별로 루프를 돌려주면서 하나의 데이터프레임으로 만들어주었다. R에서는 3차원 데이터 저장 구조에 array를 사용하면 되는데, Pandas는 원래 Panel data가 그 역할을 했지만 이제는 사용하지 않고, DataFrame의 MultiIndex나 Xarray 라이브러리를 사용하면 된다.

멀티인덱스를 사용하여 1차 업종 2차 회사로 멀티인덱스로 놓고, 데이터를 프레임에 저장했다.

 

돌리면

 

upjong.head(20)
                   시가총액     매출액    자산총계   부채총계  ...     ROE     ROA    PBR       유보율
Sector Stock                                    ...                                 
IT서비스  이루온          938     478     616    244  ...    5.97    3.52   2.46     190.8
       링네트        1,324   1,495   1,232    545  ...   11.95    6.96   1.49     892.8
       마인즈랩       1,946     113     226    772  ...   44.31  -81.57         -3,815.1
       티라유텍         697     346     331     71  ...   -3.97   -3.19   3.26   5,110.9
       소프트센         909     789     705    281  ...                   1.78     108.1
       한네트        1,124     244     544    192  ...    3.54    2.11   3.24     571.9
       갤럭시아머니트리   4,610     812   2,621  1,701  ...    4.24    1.79   4.96     436.8
       토마토시스템       422     189      85     66  ...  -46.92  -10.24             -2.3
       KG이니시스     5,148   8,102  14,005  9,483  ...   15.23    3.96   1.33   2,039.6
       현대오토에버    38,256  15,626  10,770  5,146  ...   11.09    5.78   2.85   5,251.8
       롯데정보통신     6,051   8,495   6,495  2,362  ...    7.43    4.44   1.38     523.7
       유엔젤          719     271     486    131  ...   -1.67   -2.44   1.27     654.1
       로지시스         823     329     240     76  ...    2.90    1.93   4.51     238.8
       플래티어       1,716     394     277    192  ...   39.60   11.10   4.19     360.2
       콤텍시스템      1,211   2,386   1,857    861  ...                   0.88     179.6
       소프트센우         44                         ...                  22.16          
       한솔인티큐브       483     526     418    156  ...    6.84    4.13   1.94     277.8
       브리지텍         759     443     426     89  ...    2.60    2.04   2.09     548.8
       위세아이텍      1,223     249     416    168  ...   18.82   11.34   4.62   1,142.1
       이노뎁        1,796     667     363    154  ...   35.10   16.26   4.67     585.6

 

이렇게 잘 나온다.

 

저장하자.

 

with pd.ExcelWriter('upjong.xlsx', engine='openpyxl') as writer:
    upjong.to_excel(writer)

 

잘 된다.

 

 

굳!

반응형