🐨CoalaCoding
DocsExamplesTry itBoardB반B반
🐨CoalaCoding

개발자를 위한 한국어 웹 기술 문서

문서

  • JavaScript
  • Web Publishing
  • React
  • Python

커뮤니티

  • 게시판
  • 예제 모음
  • Try it 에디터

기타

  • GitHub
  • 관리자
© 2026 CoalaCoding. All rights reserved.
  • 허깅페이스 무료 Inference API - OTT 앱 활용 가이드
  • 사진수집
  • 네이버 영화 리뷰 크롤링
  • PPT작성
  • 이메일전송
  • 파이썬 챗봇 만들기
  • 주식분석보고서
  1. 홈
  2. 문서
  3. Backend
  4. Python 프로젝트
  5. 주식분석보고서

주식분석보고서

주식분석보고서

코드 블록의 Try it Yourself 버튼으로 직접 실행할 수 있다.

구문

1. 주식 분석 보고서 자동화 프로젝트

1.1. 프로젝트 개요

주식 정보를 자동으로 수집하여 분석 보고서를 만들고 이메일로 전송

  • [최종 결과물]
  • 주식 일별 시세 데이터 수집
  • 차트 및 테이블 이미지 생성
  • PowerPoint 보고서 자동 작성
  • 이메일 자동 전송

1.2. 필요한 라이브러리 설치

라이브러리 — 다른 사람이 만들어 놓은 도구 모음이다. 파이썬에 기본 포함되지 않아 따로 설치한다.

  • matplotlib — 차트(그래프)를 그리는 도구
  • pandas — 표 형태의 데이터를 다루는 도구
  • python-pptx — 파워포인트 파일을 만드는 도구
  • beautifulsoup4 — 파이썬용 HTML 및 XML 데이터 추출
  • html5lib — 웹 브라우저(크롬, 파이어폭스 등)와 동일한 방식으로 HTML을 분석
pip install matplotlib
pip install pandas
pip install python-pptx
pip install lxml
pip install beautifulsoup4
pip install html5lib
pip install request

1.3. Step 1: 종목코드 및 일별 시세 가져오기

1.3.1. 종목코드 이해하기

종목코드 — 주식 시장에 등록된 회사마다 붙는 고유 번호이다. 사람의 주민번호와 같은 개념이다.

삼성전자 → 005930 (6자리 숫자)

1.3.2. 종목코드 다운로드

한국 거래소(KRX)에서 공개한 상장법인목록을 다운로드한다.

KRX 자료 다운로드

import pandas as pd

def get_stock_code():
    stock_code = pd.read_html("http://kind.krx.co.kr/corpgeneral/corpList.do?method=download",  encoding='cp949', header=0)[0]
    stock_code = stock_code[['회사명', '종목코드']]
    stock_code = stock_code.rename(columns={'회사명': 'company', '종목코드': 'code'})
    stock_code.code = stock_code.code.map('{:06d}'.format)
    print(stock_code)
    return stock_code
get_stock_code()

None: 1: import pandas as pd — pandas 라이브러리를 pd라는 짧은 이름으로 가져온다

3: def get_stock_code(): — 종목코드를 가져오는 함수를 만든다

4~5: pd.read_html(...) — 웹페이지의 표(HTML 테이블)를 읽어온다. header=0은 첫 번째 행을 열 이름으로 사용한다. [0]은 페이지에 있는 여러 표 중 첫 번째를 선택한다

6: stock_code[['회사명', '종목코드']] — 전체 열 중 회사명과 종목코드 두 개만 남긴다

7: .rename(columns={...}) — 열 이름을 한글에서 영어로 바꾼다

8: .map('{:06d}'.format) — 종목코드를 6자리로 맞춘다. 예: 5930 → 005930

9: return stock_code — 완성된 데이터를 돌려준다

11: stock_code = get_stock_code() — 함수를 실행하여 결과를 변수에 저장한다

12: print(stock_code.head()) — 상위 5개 데이터를 출력하여 확인한다

1.3.3. 일별 시세 가져오기

크롤링 — 웹페이지에서 데이터를 자동으로 수집하는 것이다. 네이버 금융에서 특정 회사의 일별 시세를 가져온다.

URL 구조:

http://finance.naver.com/item/sise_day.nhn?code={종목코드}&page={페이지번호}
import requests

def get_stock(code):
    df = pd.DataFrame()

    for page in range(1, 21):
        url = 'http://finance.naver.com/item/sise_day.nhn?code={code}'.format(code=code)
        url = '{url}&page={page}'.format(url=url, page=page)
        header = {'User-Agent': '<your-user-agent>'}
        res = requests.get(url, headers=header)
        current_df = pd.read_html(res.text, header=0)[0]
        df = df.append(current_df, ignore_index=True)

    return df

code = '005930'
df = get_stock(code)
print(df.head())

None: 1: import requests — 웹페이지에 접속하는 라이브러리를 가져온다

3: def get_stock(code): — 종목코드를 받아 일별 시세를 가져오는 함수를 만든다

4: df = pd.DataFrame() — 빈 표(데이터프레임)를 만든다. 여기에 데이터를 쌓는다

6: for page in range(1, 21): — 1페이지부터 20페이지까지 반복한다. 약 40주간의 데이터이다

7: url = '...{code}'.format(code=code) — 종목코드를 넣어 URL을 만든다

8: url = '{url}&page={page}'.format(...) — 페이지 번호를 URL에 추가한다

9: header = {'User-Agent': '...'} — 브라우저인 척 접속하기 위한 설정이다. 없으면 차단된다

10: res = requests.get(url, headers=header) — 해당 URL에 접속하여 페이지 내용을 가져온다

11: current_df = pd.read_html(res.text, header=0)[0] — 가져온 HTML에서 표 데이터를 추출한다

12: df = df.append(current_df, ignore_index=True) — 추출한 데이터를 기존 표에 이어 붙인다

14: return df — 모든 페이지의 데이터가 합쳐진 표를 돌려준다

16: code = '005930' — 삼성전자의 종목코드를 지정한다

17: df = get_stock(code) — 함수를 실행하여 시세 데이터를 가져온다

18: print(df.head()) — 상위 5개 데이터를 출력하여 확인한다

1.3.4. 데이터 정제 (Clean)

정제 — 수집한 데이터에서 빈 값이나 형식이 맞지 않는 부분을 정리하는 과정이다.

def clean_data(df):
    df = df.dropna()
    df = df.rename(columns={
        '날짜': 'date',
        '종가': 'close',
        '전일비': 'diff',
        '시가': 'open',
        '고가': 'high',
        '저가': 'low',
        '거래량': 'volume'
    })
    df[['close', 'diff', 'open', 'high', 'low', 'volume']] = \
        df[['close', 'diff', 'open', 'high', 'low', 'volume']].astype(int)
    df['date'] = pd.to_datetime(df['date'])
    df = df.sort_values(by=['date'], ascending=True)
    return df

df = clean_data(df)
print(df)

None: 1: def clean_data(df): — 데이터를 정제하는 함수를 만든다

2: df.dropna() — 빈 값(NaN)이 있는 행을 삭제한다

3~11: .rename(columns={...}) — 한글 열 이름을 영어로 바꾼다. 코드에서 다루기 편하다

12~13: .astype(int) — 문자형 숫자를 정수(int)로 변환한다. 계산할 수 있게 된다

14: pd.to_datetime(...) — 날짜 문자열을 날짜 형식으로 변환한다. 정렬이나 비교가 가능해진다

15: .sort_values(by=['date'], ascending=True) — 날짜 기준으로 오래된 순서부터 정렬한다

16: return df — 정제된 데이터를 돌려준다

18: df = clean_data(df) — 함수를 실행하여 정제된 데이터를 저장한다

19: print(df) — 정제된 데이터를 출력하여 확인한다

Tip: 정제 전: NaN 값, 문자형 숫자, 형식 불일치 정제 후: 정렬된 숫자 데이터, datetime 형식


1.4. Step 2: 보고자료 준비하기

수집한 데이터를 차트(그래프)와 테이블(표) 이미지로 만든다. 나중에 파워포인트에 넣기 위한 준비 단계이다.

1.4.1. 주식 차트 생성

matplotlib — 파이썬에서 그래프를 그리는 도구이다. 날짜별 종가(마감 가격)를 꺾은선 그래프로 그린다.

import matplotlib.pyplot as plt
from pandas.plotting import table
import os

plt.figure(figsize=(10, 4))
plt.plot(df['date'], df['close'])
plt.xlabel('date')
plt.ylabel('close')

chart_fname = os.path.join("res/stock_report", f'{company}_chart.png')
plt.savefig(chart_fname)
plt.show()

None: 1: import matplotlib.pyplot as plt — 그래프 그리기 도구를 plt라는 이름으로 가져온다

2: from pandas.plotting import table — 표를 이미지로 만드는 도구를 가져온다

3: import os — 파일 경로를 다루는 도구를 가져온다

5: plt.figure(figsize=(10, 4)) — 가로 10, 세로 4 크기의 그래프 틀을 만든다

6: plt.plot(df['date'], df['close']) — x축은 날짜, y축은 종가로 꺾은선 그래프를 그린다

7: plt.xlabel('date') — x축 이름을 'date'로 지정한다

8: plt.ylabel('close') — y축 이름을 'close'로 지정한다

10: os.path.join(...) — 저장할 파일 경로를 만든다

11: plt.savefig(chart_fname) — 그래프를 PNG 이미지 파일로 저장한다

12: plt.show() — 그래프를 화면에 표시한다

1.4.2. 일별 시세 테이블 생성

최근 10일간의 시세를 표 이미지로 만든다.

plt.figure(figsize=(15, 4))
ax = plt.subplot(111, frame_on=False)
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)

df_sorted = df.sort_values(by=['date'], ascending=False)
table(ax, df_sorted.head(10), loc='center', cellLoc='center', rowLoc='center')

table_fname = os.path.join("res/stock_report", f'{company}_table.png')
plt.savefig(table_fname)

None: 1: plt.figure(figsize=(15, 4)) — 가로 15, 세로 4 크기의 그래프 틀을 만든다

2: plt.subplot(111, frame_on=False) — 테두리 없는 영역을 만든다. 표만 보이게 하기 위한 설정이다

3: ax.xaxis.set_visible(False) — x축 눈금을 숨긴다

4: ax.yaxis.set_visible(False) — y축 눈금을 숨긴다

6: .sort_values(by=['date'], ascending=False) — 최신 날짜가 위에 오도록 정렬한다

7: table(ax, df_sorted.head(10), ...) — 상위 10개 데이터를 표로 그린다. 가운데 정렬이다

9: os.path.join(...) — 저장할 파일 경로를 만든다

10: plt.savefig(table_fname) — 표를 PNG 이미지 파일로 저장한다


1.5. Step 3: 보고서 작성하기

python-pptx — 파이썬으로 파워포인트(.pptx) 파일을 만드는 도구이다. 앞에서 만든 차트와 테이블 이미지를 슬라이드에 넣는다.

1.5.1. PowerPoint 기본 설정

import datetime
from pptx import Presentation
from pptx.util import Inches

today = datetime.datetime.today().strftime('%Y%m%d')
prs = Presentation()

None: 1: import datetime — 날짜/시간을 다루는 도구를 가져온다

2: from pptx import Presentation — 파워포인트 파일을 만드는 도구를 가져온다

3: from pptx.util import Inches — 인치 단위로 크기를 지정하는 도구를 가져온다

5: .today().strftime('%Y%m%d') — 오늘 날짜를 20260308 형식의 문자열로 만든다

6: prs = Presentation() — 빈 파워포인트 파일을 만든다

1.5.2. 제목 슬라이드 추가

title_slide_layout = prs.slide_layouts[0]
slide = prs.slides.add_slide(title_slide_layout)

title = slide.shapes.title
title.text = "주식 보고서"

subtitle = slide.placeholders[1]
subtitle.text = f"보고서 작성일: {today}"

None: 1: prs.slide_layouts[0] — 0번 레이아웃(제목 슬라이드)을 선택한다

2: prs.slides.add_slide(...) — 선택한 레이아웃으로 새 슬라이드를 추가한다

4: slide.shapes.title — 슬라이드의 제목 영역을 가져온다

5: title.text = "주식 보고서" — 제목에 텍스트를 넣는다

7: slide.placeholders[1] — 1번 자리표시자(부제목 영역)를 가져온다

8: subtitle.text = f"..." — 부제목에 오늘 날짜를 넣는다

1.5.3. 차트 & 테이블 슬라이드 추가

title_only_slide_layout = prs.slide_layouts[5]
slide = prs.slides.add_slide(title_only_slide_layout)

shapes = slide.shapes

latest_close = df.iloc[0]['close']
shapes.title.text = f'{company}, {latest_close} 원에 거래 마감'

left = Inches(0.5)
top = Inches(2)
width = Inches(9)
height = Inches(2.5)
pic1 = slide.shapes.add_picture(chart_fname, left, top, width=width, height=height)

left = Inches(-1)
top = Inches(4)
width = Inches(12)
height = Inches(3)
pic2 = slide.shapes.add_picture(table_fname, left, top, width=width, height=height)

None: 1: prs.slide_layouts[5] — 5번 레이아웃(제목만 있는 슬라이드)을 선택한다

2: prs.slides.add_slide(...) — 새 슬라이드를 추가한다

4: slide.shapes — 슬라이드 안의 도형 모음을 가져온다

6: df.iloc[0]['close'] — 첫 번째 행의 종가(마감 가격)를 가져온다

7: shapes.title.text = f'...' — 슬라이드 제목에 회사명과 종가를 넣는다

9~12: Inches(...) — 차트 이미지의 위치와 크기를 인치 단위로 지정한다

13: add_picture(...) — 차트 이미지를 슬라이드에 삽입한다

15~18: Inches(...) — 테이블 이미지의 위치와 크기를 지정한다

19: add_picture(...) — 테이블 이미지를 슬라이드에 삽입한다

1.5.4. 보고서 저장

ppt_fname = os.path.join("res/stock_report", 'stock_report.pptx')
prs.save(ppt_fname)
print(f"보고서 저장 완료: {ppt_fname}")

None: 1: os.path.join(...) — 저장할 파일 경로를 만든다

2: prs.save(ppt_fname) — 파워포인트 파일을 저장한다

3: print(...) — 저장 완료 메시지를 출력한다


1.6. Step 4: 이메일 전송

SMTP — 이메일을 보내는 통신 규약이다. 우체국에서 편지를 배달하는 규칙과 같다. 파이썬의 smtplib로 네이버 메일 서버에 접속하여 보고서를 첨부한 이메일을 보낸다.

1.6.1. SMTP로 이메일 보내는 함수

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import os

def send_email(smtp_info, msg):
    with smtplib.SMTP(smtp_info["smtp_server"], smtp_info["smtp_port"]) as server:
        server.starttls()
        server.login(smtp_info["smtp_user_id"], smtp_info["smtp_user_pw"])
        response = server.sendmail(msg['from'], msg['to'], msg.as_string())

        if not response:
            print("이메일 전송 성공")
        else:
            print(f"오류: {response}")

None: 1: import smtplib — 이메일 전송 도구를 가져온다

2: from email.mime.multipart import MIMEMultipart — 첨부파일이 있는 메일을 만드는 도구이다

3: from email.mime.base import MIMEBase — 파일 첨부 형식을 다루는 도구이다

4: from email import encoders — 첨부파일을 인코딩(변환)하는 도구이다

5: import os — 파일 경로를 다루는 도구를 가져온다

7: def send_email(smtp_info, msg): — SMTP 정보와 메시지를 받아 이메일을 보내는 함수이다

8: smtplib.SMTP(...) — 메일 서버에 접속한다. with를 쓰면 끝나면 자동으로 연결을 끊는다

9: server.starttls() — TLS 보안 연결을 시작한다. 이메일 내용을 암호화한다

10: server.login(...) — 아이디와 비밀번호로 로그인한다

11: server.sendmail(...) — 발신자, 수신자, 메일 내용을 넣어 전송한다

13~16: 전송 결과를 확인한다. 응답이 비어 있으면 성공, 아니면 오류를 출력한다

1.6.2. 첨부파일 포함 메시지 생성

MIME — 이메일에 텍스트, 이미지, 파일 등을 함께 담는 형식이다. 편지 봉투에 여러 서류를 넣는 것과 같다.

def make_multimsg(msg_dict):
    multi = MIMEMultipart(_subtype='mixed')

    for key, value in msg_dict.items():
        if key == 'text':
            from email.mime.text import MIMEText
            with open(value['filename'], encoding='utf-8') as fp:
                msg = MIMEText(fp.read(), _subtype=value['subtype'])
        elif key == 'image':
            from email.mime.image import MIMEImage
            with open(value['filename'], 'rb') as fp:
                msg = MIMEImage(fp.read(), _subtype=value['subtype'])
        else:
            with open(value['filename'], 'rb') as fp:
                msg = MIMEBase(value['maintype'], _subtype=value['subtype'])
                msg.set_payload(fp.read())
                encoders.encode_base64(msg)

        _, fname = os.path.split(value['filename'])
        msg.add_header('Content-Disposition', 'attachment', filename=fname)
        multi.attach(msg)

    return multi

None: 1: def make_multimsg(msg_dict): — 첨부파일 정보를 받아 메시지를 만드는 함수이다

2: MIMEMultipart(_subtype='mixed') — 여러 종류의 첨부파일을 담을 수 있는 빈 메시지를 만든다

4: for key, value in msg_dict.items(): — 첨부파일 정보를 하나씩 꺼내 반복한다

5~8: key == 'text' — 텍스트 파일이면 UTF-8로 읽어 텍스트 형식으로 첨부한다

9~12: key == 'image' — 이미지 파일이면 바이너리(rb)로 읽어 이미지 형식으로 첨부한다

13~17: 그 외 파일(pptx 등)은 범용 형식(MIMEBase)으로 읽고 base64로 인코딩한다

19: os.path.split(...) — 전체 경로에서 파일명만 분리한다

20: add_header(...) — 첨부파일의 이름을 지정한다

21: multi.attach(msg) — 만들어진 첨부파일을 메시지에 추가한다

23: return multi — 완성된 메시지를 돌려준다

1.6.3. 메일 전송 실행

smtp_info = {
    "smtp_server": "smtp.naver.com",
    "smtp_user_id": "your_email@naver.com",
    "smtp_user_pw": "your_password",
    "smtp_port": 587
}

msg_dict = {
    'application': {
        'maintype': 'application',
        'subtype': 'octet-stream',
        'filename': 'res/stock_report/stock_report.pptx'
    }
}

msg = make_multimsg(msg_dict)
msg['from'] = smtp_info["smtp_user_id"]
msg['to'] = "recipient@example.com"
msg['subject'] = "주식 분석 보고서"

send_email(smtp_info, msg)

None: 1~6: smtp_info — 메일 서버 접속 정보를 딕셔너리에 저장한다

  • smtp_server — 네이버 메일 서버 주소이다

  • smtp_port — 587번 포트를 사용한다 (TLS 보안 전송용)

8~14: msg_dict — 첨부할 파일 정보를 지정한다

  • maintype, subtype — 파일 종류를 지정한다. octet-stream은 범용 바이너리 파일이다

  • filename — 첨부할 파일 경로이다

16: make_multimsg(msg_dict) — 첨부파일이 포함된 메시지를 만든다

17: msg['from'] — 보내는 사람 이메일을 지정한다

18: msg['to'] — 받는 사람 이메일을 지정한다

19: msg['subject'] — 메일 제목을 지정한다

21: send_email(smtp_info, msg) — 이메일을 전송한다

Warning: smtp_user_id와 smtp_user_pw에 실제 아이디와 비밀번호를 넣어야 한다. 코드에 비밀번호를 직접 적으면 보안에 위험하므로 환경변수나 별도 설정 파일을 사용하는 것이 좋다.


1.7. 전체 코드 통합

import pandas as pd
import requests
import matplotlib.pyplot as plt
from pandas.plotting import table
from pptx import Presentation
from pptx.util import Inches
import smtplib
import datetime
import os
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email import encoders

# ─── 함수 정의 ───

def get_stock_code():
    stock_code = pd.read_html('http://kind.krx.co.kr/corpgeneral/corpList.do?method=download', header=0)[0]
    stock_code = stock_code[['회사명', '종목코드']]
    stock_code = stock_code.rename(columns={'회사명': 'company', '종목코드': 'code'})
    stock_code.code = stock_code.code.map('{:06d}'.format)
    return stock_code

def get_stock(code):
    df = pd.DataFrame()
    for page in range(1, 21):
        url = 'http://finance.naver.com/item/sise_day.nhn?code={code}'.format(code=code)
        url = '{url}&page={page}'.format(url=url, page=page)
        header = {'User-Agent': '<your-user-agent>'}
        res = requests.get(url, headers=header)
        current_df = pd.read_html(res.text, header=0)[0]
        df = df.append(current_df, ignore_index=True)
    return df

def clean_data(df):
    df = df.dropna()
    df = df.rename(columns={
        '날짜': 'date',
        '종가': 'close',
        '전일비': 'diff',
        '시가': 'open',
        '고가': 'high',
        '저가': 'low',
        '거래량': 'volume'
    })
    df[['close', 'diff', 'open', 'high', 'low', 'volume']] = \
        df[['close', 'diff', 'open', 'high', 'low', 'volume']].astype(int)
    df['date'] = pd.to_datetime(df['date'])
    df = df.sort_values(by=['date'], ascending=True)
    return df

def create_chart(df, company):
    plt.figure(figsize=(10, 4))
    plt.plot(df['date'], df['close'])
    plt.xlabel('date')
    plt.ylabel('close')
    chart_fname = os.path.join("res/stock_report", f'{company}_chart.png')
    plt.savefig(chart_fname)
    plt.show()
    return chart_fname

def create_table(df, company):
    plt.figure(figsize=(15, 4))
    ax = plt.subplot(111, frame_on=False)
    ax.xaxis.set_visible(False)
    ax.yaxis.set_visible(False)
    df_sorted = df.sort_values(by=['date'], ascending=False)
    table(ax, df_sorted.head(10), loc='center', cellLoc='center', rowLoc='center')
    table_fname = os.path.join("res/stock_report", f'{company}_table.png')
    plt.savefig(table_fname)
    return table_fname

def create_pptx(df, company, chart_fname, table_fname):
    today = datetime.datetime.today().strftime('%Y%m%d')
    prs = Presentation()

    title_slide_layout = prs.slide_layouts[0]
    slide = prs.slides.add_slide(title_slide_layout)
    title = slide.shapes.title
    title.text = "주식 보고서"
    subtitle = slide.placeholders[1]
    subtitle.text = f"보고서 작성일: {today}"

    title_only_slide_layout = prs.slide_layouts[5]
    slide = prs.slides.add_slide(title_only_slide_layout)
    shapes = slide.shapes
    latest_close = df.iloc[-1]['close']
    shapes.title.text = f'{company}, {latest_close} 원에 거래 마감'

    left = Inches(0.5)
    top = Inches(2)
    width = Inches(9)
    height = Inches(2.5)
    slide.shapes.add_picture(chart_fname, left, top, width=width, height=height)

    left = Inches(-1)
    top = Inches(4)
    width = Inches(12)
    height = Inches(3)
    slide.shapes.add_picture(table_fname, left, top, width=width, height=height)

    ppt_fname = os.path.join("res/stock_report", 'stock_report.pptx')
    prs.save(ppt_fname)
    print(f"보고서 저장 완료: {ppt_fname}")
    return ppt_fname

def send_email(smtp_info, msg):
    with smtplib.SMTP(smtp_info["smtp_server"], smtp_info["smtp_port"]) as server:
        server.starttls()
        server.login(smtp_info["smtp_user_id"], smtp_info["smtp_user_pw"])
        response = server.sendmail(msg['from'], msg['to'], msg.as_string())
        if not response:
            print("이메일 전송 성공")
        else:
            print(f"오류: {response}")

def make_multimsg(msg_dict):
    multi = MIMEMultipart(_subtype='mixed')
    for key, value in msg_dict.items():
        if key == 'text':
            with open(value['filename'], encoding='utf-8') as fp:
                msg = MIMEText(fp.read(), _subtype=value['subtype'])
        elif key == 'image':
            with open(value['filename'], 'rb') as fp:
                msg = MIMEImage(fp.read(), _subtype=value['subtype'])
        else:
            with open(value['filename'], 'rb') as fp:
                msg = MIMEBase(value['maintype'], _subtype=value['subtype'])
                msg.set_payload(fp.read())
                encoders.encode_base64(msg)
        _, fname = os.path.split(value['filename'])
        msg.add_header('Content-Disposition', 'attachment', filename=fname)
        multi.attach(msg)
    return multi

# ─── 실행 ───

company = '삼성전자'

# Step 1: 데이터 수집
stock_code_df = get_stock_code()
code = stock_code_df[stock_code_df.company == company].code.values[0].strip()
df = get_stock(code)
df = clean_data(df)

# Step 2: 보고자료 생성
chart_fname = create_chart(df, company)
table_fname = create_table(df, company)

# Step 3: 보고서 작성
ppt_fname = create_pptx(df, company, chart_fname, table_fname)

# Step 4: 이메일 전송
smtp_info = {
    "smtp_server": "smtp.naver.com",
    "smtp_user_id": "your_email@naver.com",
    "smtp_user_pw": "your_password",
    "smtp_port": 587
}

msg_dict = {
    'application': {
        'maintype': 'application',
        'subtype': 'octet-stream',
        'filename': ppt_fname
    }
}

msg = make_multimsg(msg_dict)
msg['from'] = smtp_info["smtp_user_id"]
msg['to'] = "recipient@example.com"
msg['subject'] = "주식 분석 보고서"

send_email(smtp_info, msg)

print("모든 작업이 완료되었다!")

목차

  • 구문