본문 바로가기
  • You find inspiration to create your own path !
personal activity/stock

종목 이름 가져오기] ticker, name, sector 응용 #1

by ToolBOX01 2025. 9. 13.
반응형

EPS (Earnings Per Share)

1주당 순이익(EPS, Earnings Per Share)은 기업의 순이익을 발행된 주식 수로 나눈 값으로, 한 주당 얼마의 이익을 창출했는가?를 나타내는 핵심 재무 지표입니다. 투자자가 기업의 수익성을 평가하고 주가를 분석할 때 널리 활용됩니다.

  • 순이익: 세후 이익(법인세, 이자, 기타 비용 등을 제외한 순수한 이익).
  • 발행된 주식 수: 현재 시장에서 거래되는 주식 총수 (희석 가능성 제외)
  • 수익성 평가: EPS가 높을수록 기업이 효율적으로 이익을 내고 있음을 의미합니다.
  • 배당 여력: EPS가 높으면 배당금으로 지급할 능력이 커져 투자 매력도가 높아집니다.
  • 성장성 예측: 추정 EPS(미래 예상 이익)를 통해 기업의 성장 가능성을 미리 가늠할 수 있습니다.

📌 주의 사항

  • 희석 EPS(Diluted EPS):
    주식 옵션, 전환사채 등이 행사되어 주식 수가 늘어날 경우를 가정한 EPS입니다. 기본 EPS보다 낮게 계산됩니다.
  • 일시적 요인: 일회성 비용이나 이익 변동에 따라 EPS가 왜곡될 수 있으므로, 장기적 추세를 함께 봐야 합니다.
  • 산업별 차이: 업종별로 평균 EPS가 다르므로 동일 산업 내에서 비교해야 합니다.

※ 2025년 9월 12일 대한민국 주식시장의 ticker 및 주식종목 이름, sector 다운로드

ticker.xlsx
0.09MB

※ ticker.xlsx 파일을 이용한 EPS (Earnings Per Share) 값 가져오는 클로링 파이썬 코드

"https://finance.naver.com/sise"를 사용하여 주식 종목별 EPS (Earnings Per Share) 값 엑셀 파일에 입력 합니다.
네이버 사이트에 값이 없는 경우, 표시 하지 않습니다. 그러나 디버그 HTML 파일이 저장 됩니다

import requests
from bs4 import BeautifulSoup
import pandas as pd
from openpyxl import load_workbook
import re
import time
import os

# 설정
FILE_PATH = "ticker.xlsx"
SHEET_NAME = "tickersheet"
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
SAVE_DEBUG_HTML = True   # 못 찾은 종목 HTML 저장 여부

# 숫자 정리 함수
def clean_num(s):
    if not s: 
        return None
    s = str(s).replace('\xa0',' ').strip()
    m = re.search(r'-?\d{1,3}(?:,\d{3})*(?:\.\d+)?|-?\d+(?:\.\d+)?', s)
    if m:
        return m.group(0).replace(',', '')
    return None

# EPS 추출 함수
def extract_eps_from_soup(soup):
    # 1) id 기반
    for sel in ['#_eps', 'em#_eps', 'span#_eps', 'strong#_eps']:
        tag = soup.select_one(sel)
        if tag:
            v = clean_num(tag.get_text())
            if v: return v

    # 2) aside_invest_info 블럭
    invest = soup.select_one('.aside_invest_info')
    if invest:
        for tr in invest.select('tr'):
            tds = tr.find_all(['th','td'])
            if len(tds) >= 2:
                if 'EPS' in tds[0].get_text(strip=True):
                    v = clean_num(tds[1].get_text())
                    if v: return v

    # 3) "EPS" 텍스트 주변
    for text_node in soup.find_all(string=re.compile(r'\bEPS\b', re.I)):
        tr = text_node.find_parent('tr')
        if tr:
            tds = tr.find_all(['td','th'])
            for i, td in enumerate(tds):
                if 'EPS' in td.get_text(strip=True):
                    if i+1 < len(tds):
                        v = clean_num(tds[i+1].get_text())
                        if v: return v

    # 4) 전체 텍스트에서 탐색
    page_text = soup.get_text(" ", strip=True)
    m = re.search(r'EPS[^0-9\-+]*([-]?\d{1,3}(?:,\d{3})*(?:\.\d+)?)', page_text, re.I)
    if m:
        return clean_num(m.group(1))

    return None


# ---- 메인 실행 ----
df = pd.read_excel(FILE_PATH, sheet_name=SHEET_NAME)
eps_list = []

total = len(df)
start_time = time.time()

for idx, row in df.iterrows():
    code = str(row["Ticker"]).zfill(6)
    name = row.get("Name", "")
    print(f"▶ [{idx+1}/{total}] [{code}] {name} EPS 조회 중...")

    url = f"https://finance.naver.com/item/main.naver?code={code}"
    try:
        res = requests.get(url, headers=HEADERS, timeout=10)
        res.encoding = res.apparent_encoding or 'utf-8'
        soup = BeautifulSoup(res.text, "html.parser")
    except Exception as e:
        print(f"   ✖ HTTP/네트워크 오류: {e}")
        eps_list.append(None)
        continue

    eps_value = extract_eps_from_soup(soup)
    if eps_value is None:
        print("   → EPS: None (찾지 못함)")
        if SAVE_DEBUG_HTML:
            debug_name = f"debug_{code}.html"
            with open(debug_name, "w", encoding="utf-8") as f:
                f.write(res.text)
            print(f"     (디버그 HTML 저장: {os.path.abspath(debug_name)})")
    else:
        print(f"   → EPS: {eps_value}")

    eps_list.append(eps_value)
    time.sleep(0.3)  # 서버 부담 완화

elapsed = time.time() - start_time
found = sum(1 for v in eps_list if v is not None)
print(f"\n완료: {found}/{total} 개 항목에서 EPS를 찾음 (소요 {elapsed:.1f}초)")

# ---- D열만 갱신 ----
book = load_workbook(FILE_PATH)
ws = book[SHEET_NAME]

# D2부터 EPS 값 기록
for i, val in enumerate(eps_list, start=2):  
    ws[f"D{i}"] = val

book.save(FILE_PATH)
print("✅ EPS 크롤링 완료 후 D열만 갱신하여 저장되었습니다.")

※ 2025년 9월 12일 대한민국 주식시장의 ticker 및 주식종목 이름, sector, EPS 다운로드

ticker.xlsx
0.11MB


▣ PER( Price-to-Earnings Ratio)

PER(주가수익비율, Price-to-Earnings Ratio)은 주가가 기업의 이익 대비 얼마나 평가받고 있는지를 나타내는 대표적인 재무 지표입니다. 투자자들이 기업의 상대적 가치를 판단하고, 저평가/고평가 여부를 분석할 때 활용됩니다.

📌PER(주가수익비율, Price-to-Earnings Ratio) 의미: "주가가 이익 대비 몇 배인가?"를 나타냅니다.

  • PER이 높다 → 이익 대비 주가가 비싸게 평가됨 (고평가).
  • PER이 낮다 → 이익 대비 주가가 저렴하게 평가됨 (저평가).

예시)  PER이 10배 :   기업이 이익 1원을 얻기 위해 10배의 가격을 지불하고 있다는 의미입니다.

📌저평가 vs. 고평가 판단

  • 동종업계 평균 PER과 비교합니다.
    예: 반도체 업종의 평균 PER이 20이라면, 해당 기업의 PER이 10이면 저평가, 30이면 고평가로 판단합니다.
  • 역사적 PER과 비교하여 추세 분석를 분석 합니다.

📌평가 방법 팁

  • 추정 PER을 함께 보세요!
    - 미래 예상 EPS로 계산한 추정 PER이 현재 PER보다 낮다면 매수 기회로 볼 수 있습니다.
  • PBR, ROE와 함께 분석하세요.
    - PER만으로는 기업의 재무 상태를 완전히 파악하기 어렵습니다.
  • 배당률과 결합해 보세요.
    - PER이 낮고 배당률이 높다면 안정적인 투자 대상이 될 수 있습니다.
  • 낮은 PER = 이익 대비 저평가, 높은 PER = 이익 대비 고평가
  • 업종 평균과 역사적 추이를 반드시 비교하세요!

※ ticker.xlsx 파일을 이용한 PER( Price-to-Earnings Ratio)값 가져오는 클로링 파이썬 코드

네이버 사이트에 값이 없는 경우, 표시 하지 않습니다. 그러나 디버그 HTML 파일이 저장 됩니다

import requests
from bs4 import BeautifulSoup
import pandas as pd
from openpyxl import load_workbook
import re
import time
import os

# Configuration
FILE_PATH = "ticker.xlsx"       # 엑셀 파일 경로
SHEET_NAME = "tickersheet"      # 시트 이름
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
SAVE_DEBUG_HTML = True          # PER 못 찾을 경우 HTML 저장

# Function to clean and extract numbers
def clean_num(s):
    if s is None:
        return None
    s = str(s).replace('\xa0',' ').strip()

    if "N/A" in s.upper() or s.strip() == '-' or s.strip() == '':
        return None

    m = re.search(r'-?\d{1,3}(?:,\d{3})*(?:\.\d+)?|-?\d+(?:\.\d+)?', s)
    if m:
        return m.group(0).replace(',', '')
    return None

# Function to extract PER from BeautifulSoup object
def extract_per_from_soup(soup):
    # aside_invest_info 안의 투자정보 블록
    invest = soup.select_one('.aside_invest_info')
    if invest:
        for tr in invest.select('tr'):
            tds = tr.find_all(['th', 'td'])
            if len(tds) >= 2:
                header_text = tds[0].get_text(strip=True)

                # "동일업종", "업종", "추정" PER은 건너뛰기
                if 'PER' in header_text and not any(x in header_text for x in ['동일업종','업종','추정']):
                    val_cell = tds[1]
                    em = val_cell.select_one('em')
                    if em:
                        v = clean_num(em.get_text(strip=True))
                        return v
                    else:
                        v = clean_num(val_cell.get_text(strip=True))
                        return v
    return None

# ---- Main Execution ----
try:
    df = pd.read_excel(FILE_PATH, sheet_name=SHEET_NAME)
except FileNotFoundError:
    print(f"Error: The file '{FILE_PATH}' was not found. Please check the file path.")
    exit()

per_list = []

total = len(df)
start_time = time.time()

for idx, row in df.iterrows():
    code = str(row["Ticker"]).zfill(6)
    name = row.get("Name", "")
    print(f"▶ [{idx+1}/{total}] [{code}] {name} PER 조회 중...")

    url = f"https://finance.naver.com/item/main.naver?code={code}"
    try:
        res = requests.get(url, headers=HEADERS, timeout=10)
        res.encoding = res.apparent_encoding or 'utf-8'
        soup = BeautifulSoup(res.text, "html.parser")
    except Exception as e:
        print(f"   ✖ HTTP/네트워크 오류: {e}")
        per_list.append(None)
        continue

    per_value = extract_per_from_soup(soup)
    if per_value is None:
        print("   → PER: None (찾지 못함)")
        if SAVE_DEBUG_HTML:
            debug_name = f"debug_{code}.html"
            with open(debug_name, "w", encoding="utf-8") as f:
                f.write(res.text)
            print(f"      (디버그 HTML 저장: {os.path.abspath(debug_name)})")
    else:
        print(f"   → PER: {per_value}")

    per_list.append(per_value)
    time.sleep(0.3)  # 서버 부하 방지

elapsed = time.time() - start_time
found = sum(1 for v in per_list if v is not None)
print(f"\n완료: {found}/{total} 개 항목에서 PER을 찾음 (소요 {elapsed:.1f}초)")

# ---- Update only column E ----
try:
    book = load_workbook(FILE_PATH)
    ws = book[SHEET_NAME]

    # Write PER values starting from E2
    for i, val in enumerate(per_list, start=2):
        ws[f"E{i}"] = val

    book.save(FILE_PATH)
    print("✅ PER 크롤링 완료 후 E열만 갱신하여 저장되었습니다.")
except FileNotFoundError:
    print(f"Error: The file '{FILE_PATH}' was not found. Could not update.")

 

ticker.xlsx
0.13MB

 

대한 민국의 주식 종목은 대략 2878개 입니다. 시간이 지남에 따라 추가되는 경우도 있지만, 퇴출되는 경우도 있습니다.
EPS, 주식수, 주당 가격, PBR,PER등 다양한 지표는 매분, 매 시간마다 조금씩 변합니다. 그때마다 변경 되는 데이터를 빠르게 받아오고, 시각화 하려면 대단히 빠른 하드웨어와 다양한 기능이 있는 소프트웨어가 필요 합니다.  데이터 베이스와 엑셀 프로그램이 이기능을 제공 해왔으나, 데이터를 가공하여 사용 하는데 어려움이 있습니다. 전문적인 지식과 비용을 들여, 데이터를 가져올수 있습니다. 그러나 AI의 발전으로 비 전문가도 데이터를 무료로 가져올수 있고, 자신만의 프로그램을 만들수 있습니다. AI, 파이썬, 무료 데이터 베이스가 이러한 것을 가능 하게 합니다.

주식정보 파이썬

 

by korealionkk@gmail.com


반응형