import requests #특정 사이트에서 값을 요청하기 위한 모듈
from bs4 import BeautifulSoup #데이터 패싱을 위한 모듈 설치
import sqlite3 #SQL형태의 DB 모듈 설치를 위해 생성
from sqlite3 import Error #DB의 Erorr 모듈 설치
import time #실시간 데이터를 받아오기 위한 모듈 설치
# SQLite 데이터베이스 생성 또는 연결하는 함수
def create_connection(db_file):
try:
conn = sqlite3.connect(db_file) #기존 데이터베이스 파일과 연결 시도
return conn #연결 성공시 연결한 DB 데이터베이스 안의 값을 반환
except Error as e: #eroor 입력하기 귀찮으니 e 라는 변수변환
print(e) #오류 출력
return None #리턴값 0==오류출력
# 주식 가격을 저장할 테이블을 생성하는 함수 (테이블이 존재하지 않을 경우)
def create_table(conn):
create_table_sql = """
CREATE TABLE IF NOT EXISTS stock_prices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_code TEXT,
company_name TEXT,
price TEXT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);
"""
# 테이블 안에 가격이 포함됐을경우
# 테이블을 구분하는 핵심 키(ID)
# 회사코드(text)
# 회사 이름(text)
# 종목 현재 가격(text)
# 검색했던 실시간(DATETIME)
try:
cursor = conn.cursor() #연결한 DB에 커서 생성
cursor.execute(create_table_sql) #위에서 설정한 스키마 구조대로 DB 테이블 생성
except Error as e:#에러가 있으면
print(e)#에러출력
# 레코드를 데이터베이스에 삽입하는 함수
def insert_record(conn, company_code, company_name, price):
insert_sql = """
INSERT INTO stock_prices (company_code, company_name, price)
VALUES (?, ?, ?);
"""#변수가 실제 저장될 값 개수만큼 공간을 할당해줘야 함
try:
cursor = conn.cursor() #커서 접속
cursor.execute(insert_sql, (company_code, company_name, price)) #sql구조대를 받아와서 거기에 받아온 변수대로 입력
conn.commit() #데이터 처리 끝낸 후 전송
except Error as e:
print(e)
# BeautifulSoup 객체를 얻는 함수
def get_bs_obj(company_code): #네이버...?
url = "https://finance.naver.com/item/main.nhn?code=" + company_code #url형태가 주소+회사코드 형태라 자동 처리가 쉬움
#url 사이트는 네이버 증권+종목번호 형태
result = requests.get(url)
bs_obj = BeautifulSoup(result.content, "html.parser") #html 패싱으로 참조변수형태로 선언
return bs_obj #받은 값을 bs화 해서 반환
# 주식 가격을 얻는 함수
def get_price(company_code):
bs_obj = get_bs_obj(company_code) #종목 코드드에 따라 검색하여 주식 가격을 가져옴
no_today = bs_obj.find("p", {"class":"no_today"})
#사이트에서 HTML 형태가 이런 형태이므로 긁어올때도 형태를 맞추어 줘야함
#그리고 가져온 형태를 변수에 저장해야함
blind_now = no_today.find("span", {"class":"blind"})
return blind_now.text #받은 값을 텍스트 형태로 반환
# 테이블을 삭제하고 다시 생성하는 함수
def reset_table(conn):
drop_table_sql = """
DROP TABLE IF EXISTS stock_prices
"""
# DROP은 데이터베이스 내용물을 전부 날리는 명령어다
cursor = conn.cursor()
cursor.execute(drop_table_sql)
create_table(conn)
# 메인 함수
def main():
db_file = "stock_prices.db" # 데이터베이스 파일명
conn = create_connection(db_file) # 데이터베이스 연결 생성
if conn is not None:
create_table(conn) # 테이블 생성
try:
while True:
#검색 입력 형식 : 종목명 종목코드
# 테이블 초기화 여부를 확인하고 초기화하도록 요청
qustion_key = input("종목 검색기록을 초기화 하시겠습니까? (y/n)? \n")
if qustion_key.lower() == 'y': #y를 입력할경우 검색기록 초기화
reset_table(conn)
print("검색 데이터베이스가 초기화되었습니다. 지금부터 새로 입력되는 정보는 검색기록에 남습니다. 종료하시려면 e를 입력해주세요.")
print("검색할 종목명을 입력해주세요 : ")
elif qustion_key.lower() == 'n': #n 입력할경우 그냥
print("종목 검색을 계속합니다. 종료하시려면 ctrl+c를 입력해주세요. \n")
print("검색할 종목코드를 입력해주세요 : ")
company_name, company_code= map(str,input().split())
#수정사항2. 만약 특정 키워드 만으로 커피를 검색하게 할순 없을까?
#수정사항3. 주식이 아니라 다양한 원자재(철, 구리, 석유, 커피) 등등의 정보를 여러 사이트에서 크롤링 해올수는 없을까?
#수정사항4. 만약 변동폭이 5%이상이라면 크롬으로 알림을 보낼수는 없을까?(API 기능)
#수정사항5. 미국주식과 국내주식, 원자재의 카테고리를 분리할수는 없을까? 분리한다면 무슨 키워드를 입력해야 그 카테고리로 이동하게 할 수 있을까?
#수정사항6. 만약 검색기록을 최근 검색기록처럼 조회하는 방법을 구현할수는 없을까?
price = get_price(company_code)
print(f"회사명: {company_name} , 종목코드 : {company_code}, 현재가: {price}")
insert_record(conn, company_code, company_name, price)
# 종료 조건: Ctrl+C로 종료할 수 있도록 대기
time.sleep(5)
except KeyboardInterrupt:
print("프로그램을 종료합니다.")
conn.close() # 데이터베이스 연결 닫기
if __name__ == "__main__":
main() # 메인 함수 호출