더북(TheBook)

make_up_universe.py

import requests
from bs4 import BeautifulSoup
import numpy as np
import pandas as pd
from datetime import datetime

BASE_URL = 'https://finance.naver.com/sise/sise_market_sum.nhn?sosok='
CODES = [0, 1]
START_PAGE = 1
fields = []

now = datetime.now()
formattedDate = now.strftime("%Y%m%d")

def execute_crawler():
    df_total = [] ------ KOSPI, KOSDAQ 종목을 하나로 합치는 데 사용할 변수

    for code in CODES: ------ CODES에 담긴 KOSPI, KOSDAQ 종목 모두를 크롤링하려고 for 문 사용

        res = requests.get(BASE_URL + str(CODES[0])) ------ 전체 페이지 수를 가져오는 코드
        page_soup = BeautifulSoup(res.text, 'lxml')
        total_page_num = page_soup.select_one('td.pgRR > a') ------ ‘맨뒤’에 해당하는 태그를 기준으로 전체 페이지 수 추출
        total_page_num = int(total_page_num.get('href').split('=')[-1])
        ipt_html = page_soup.select_one('div.subcnt_sise_item_top') ------ 조회할 수 있는 항목 정보들 추출

        global fields ------ 전역 변수 fields에 항목들을 담아 다른 함수에서도 접근 가능하도록 만듦
        fields = [item.get('value') for item in ipt_html.select('input')]
        result = [crawler(code, str(page)) for page in range(1, total_page_num + 1)] ------ 페이지마다 존재하는 모든 종목의 항목 정보를 크롤링해서 result에 저장(여기서 crawler 함수가 한 페이지씩 크롤링해 오는 역할 담당)
        df = pd.concat(result, axis=0, ignore_index=True) ------ 전체 페이지를 저장한 result를 하나의 데이터프레임으로 만듦

        df_total.append(df) ------ df 변수는 KOSPI, KOSDAQ별로 크롤링한 종목 정보고, 이를 하나로 합치고자 df_total에 추가

    df_total = pd.concat(df_total) ------ df_total을 하나의 데이터프레임으로 만듦
    df_total.reset_index(inplace=True, drop=True) ------ 합친 데이터 프레임의 index 번호를 새로 매김

    df_total.to_excel('NaverFinance.xlsx') ------ 전체 크롤링 결과를 엑셀로 출력

    return df_total ------ 크롤링 결과를 반환

def crawler(code, page):

    global fields

    data = {'menu': 'market_sum', 
            'fieldIds': fields,
            'returnUrl': BASE_URL + str(code) + "&page=" + str(page)} ------ Naver Finance에 전달할 값들 세팅(요청을 보낼 때는 menu, fieldIds, returnUrl을 지정해서 보내야 함)

    res = requests.post('https://finance.naver.com/sise/field_submit.nhn', data=data) ------ 네이버로 요청을 전달(post 방식)

    page_soup = BeautifulSoup(res.text, 'lxml')
   
    table_html = page_soup.select_one('div.box_type_l')
    header_data = [item.get_text().strip() for item in table_html.select('thead th')] ------ 크롤링할 table의 html을 가져오는 코드(크롤링 대상 요소의 클래스는 웹 브라우저에서 확인)
                  [1:-1] ------ column 이름을 가공
    inner_data = [item.get_text().strip() for item in table_html.find_all(lambda x: (x.name == 'a' and 'tltle' in x.get('class', [])) or (x.name == 'td' and 'number' in x.get('class', []))
    )] ------ 종목명 + 수치 추출(a.title = 종목명, td.number = 기타 수치)

    no_data = [item.get_text().strip() for item in table_html.select('td.no')] ------ 페이지마다 있는 종목의 순번 가져오기
    number_data = np.array(inner_data)

    number_data.resize(len(no_data), len(header_data)) ------ 가로×세로 크기에 맞게 행렬화
    
    df = pd.DataFrame(data=number_data, columns=header_data) ------ 한 페이지에서 얻은 정보를 모아 데이터프레임으로 만들어 반환
    return df

if __name__ == "__main__":
    print('Start!')
    execute_crawler()
    print('End')
신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.