본문 바로가기
ETC/Python

네이버 증권 파이썬(Python)을 이용하여 주식 정보 크롤링하기(Request, BeautifulSoup) 2편

by Guardy 2024. 10. 28.
728x90
반응형

지난글 보러가기 https://dev-guardy.tistory.com/117

 

네이버 증권 파이썬(Python)을 이용하여 주식 정보 크롤링하기(Request, BeautifulSoup) 1편

오늘은 파이썬을 이용하여 네이버 증권에서 시가총액순으로 나와있는 종목 정보를 크롤링하려고 한다.다음 페이지 주소는 다음과 같다.https://finance.naver.com/sise/sise_market_sum.naver?sosok=0&page=1 시가

dev-guardy.tistory.com

저번에 만들었던 코드는 다음과 같다.

import requests
from bs4 import BeautifulSoup
import re

resp = requests.get('https://finance.naver.com/sise/sise_market_sum.naver?sosok=0&page=1')
html_data = resp.text

soup = BeautifulSoup(html_data, 'html.parser')

tbody = soup.find('tbody')

stocks = []


for row in tbody.find_all('tr'):
    tds = row.find_all('td')
    
    if len(tds) < 12:
        continue

    stock_name_tag = tds[1].find('a')
    if stock_name_tag:
        stock_name = stock_name_tag.text.strip()
        href = stock_name_tag['href']
        stock_code_match = re.search(r'code=(\d+)', href)
        stock_code = stock_code_match.group(1) if stock_code_match else ''
    else:
        stock_name = ''
        stock_code = ''

    current_price = tds[2].text.strip().replace(',', '')
    market_cap = tds[6].text.strip().replace(',', '')
    num_shares = tds[7].text.strip().replace(',', '')
    foreign_ratio = tds[8].text.strip().replace(',', '')
    volume = tds[9].text.strip().replace(',', '')
    per = tds[10].text.strip()
    roe = tds[11].text.strip()

    stock_data = {
        '종목명': stock_name,
        '종목코드': stock_code,
        '현재가': current_price,
        '시가총액': market_cap,
        '상장주식수': num_shares,
        '외국인비율': foreign_ratio,
        '거래량': volume,
        'PER': per,
        'ROE': roe
    }

    stocks.append(stock_data)

for stock in stocks:
    print(stock)

이 코드의 경우 코스피 첫번째 페이지만 가져오기 때문에 코스피, 코스닥 전체 종목 정보를 가져오기 위해서는 반복문을 돌려야한다.

우선 코스피의 경우

46페이지

코스닥의 경우

36페이지까지 있다.

 

이제 코드를 작성해보자.

먼저 최종결과를 jsonl로 저장할것이기 때문에 라이브러리 부분을 수정해준다.

그 다음 market 정보에 대해 dict 형태로 정의해준다.

import requests
from bs4 import BeautifulSoup
import re
import json
import time

markets = {
    '코스피': {'sosok': '0', 'pages': 46},
    '코스닥': {'sosok': '1', 'pages': 36}
}

stocks = []

그 다음 큰 for문을 열어 코스피와 코스닥을 돌게 해준다.

for market_name, market_info in markets.items():
    sosok = market_info['sosok']
    total_pages = market_info['pages']
    
    print(f"{market_name} 정보 가져오기 ...")

위 for문 안에 저번에 만들었던 코드에서 sosok과 page부분을 변수로 바꿔준다음에 재사용하여 다음과 같이 코드를 작성한다.

for page in range(1, total_pages + 1):
        url = f'https://finance.naver.com/sise/sise_market_sum.naver?sosok={sosok}&page={page}'
        resp = requests.get(url)
        html_data = resp.text

        soup = BeautifulSoup(html_data, 'html.parser')

        tbody = soup.find('tbody')

        for row in tbody.find_all('tr'):
            tds = row.find_all('td')
            
            if len(tds) < 12:
                continue

            stock_name_tag = tds[1].find('a')
            if stock_name_tag:
                stock_name = stock_name_tag.text.strip()
                href = stock_name_tag['href']
                stock_code_match = re.search(r'code=(\d+)', href)
                stock_code = stock_code_match.group(1) if stock_code_match else ''
            else:
                stock_name = ''
                stock_code = ''

            current_price = tds[2].text.strip().replace(',', '')
            market_cap = tds[6].text.strip().replace(',', '')
            num_shares = tds[7].text.strip().replace(',', '')
            foreign_ratio = tds[8].text.strip().replace(',', '')
            volume = tds[9].text.strip().replace(',', '')
            per = tds[10].text.strip()
            roe = tds[11].text.strip()

            stock_data = {
                '구분': market_name,
                '종목명': stock_name,
                '종목코드': stock_code,
                '현재가': current_price,
                '시가총액': market_cap,
                '상장주식수': num_shares,
                '외국인비율': foreign_ratio,
                '거래량': volume,
                'PER': per,
                'ROE': roe
            }

            stocks.append(stock_data)
        
        time.sleep(0.5)

마지막으로 모든 종목 정보가 stocks 리스트에 담겼다면 jsonl형태로 저장해준다.

print("종목 정보 크롤링 완료")

with open('stocks.jsonl', 'w', encoding='utf-8') as f:
    for stock in stocks:
        json_line = json.dumps(stock, ensure_ascii=False)
        f.write(json_line + '\n')

print("stocks.jsonl로 저장 완료")

코드를 돌리면 다음과 같이 jsonl로 잘 저장된 것을 확인 할 수 있다.

stocks.jsonl

최종 코드는 다음과 같다.

import requests
from bs4 import BeautifulSoup
import re
import json
import time

markets = {
    '코스피': {'sosok': '0', 'pages': 46},
    '코스닥': {'sosok': '1', 'pages': 36}
}

stocks = []

for market_name, market_info in markets.items():
    sosok = market_info['sosok']
    total_pages = market_info['pages']
    
    print(f"{market_name} 정보 가져오기 ...")
    
    for page in range(1, total_pages + 1):
        url = f'https://finance.naver.com/sise/sise_market_sum.naver?sosok={sosok}&page={page}'
        resp = requests.get(url)
        html_data = resp.text

        soup = BeautifulSoup(html_data, 'html.parser')

        tbody = soup.find('tbody')

        for row in tbody.find_all('tr'):
            tds = row.find_all('td')
            
            if len(tds) < 12:
                continue

            stock_name_tag = tds[1].find('a')
            if stock_name_tag:
                stock_name = stock_name_tag.text.strip()
                href = stock_name_tag['href']
                stock_code_match = re.search(r'code=(\d+)', href)
                stock_code = stock_code_match.group(1) if stock_code_match else ''
            else:
                stock_name = ''
                stock_code = ''

            current_price = tds[2].text.strip().replace(',', '')
            market_cap = tds[6].text.strip().replace(',', '')
            num_shares = tds[7].text.strip().replace(',', '')
            foreign_ratio = tds[8].text.strip().replace(',', '')
            volume = tds[9].text.strip().replace(',', '')
            per = tds[10].text.strip()
            roe = tds[11].text.strip()

            stock_data = {
                '구분': market_name,
                '종목명': stock_name,
                '종목코드': stock_code,
                '현재가': current_price,
                '시가총액': market_cap,
                '상장주식수': num_shares,
                '외국인비율': foreign_ratio,
                '거래량': volume,
                'PER': per,
                'ROE': roe
            }

            stocks.append(stock_data)
        
        time.sleep(0.5)

print("종목 정보 크롤링 완료")

with open('stocks.jsonl', 'w', encoding='utf-8') as f:
    for stock in stocks:
        json_line = json.dumps(stock, ensure_ascii=False)
        f.write(json_line + '\n')

print("stocks.jsonl로 저장 완료")

 

도움이 되셨다면 공감과 댓글 부탁드립니다.

728x90
반응형