웹스쿨

키움 로그인 창 띄우기 본문

개인 프로젝트/파이썬 뉴스매매

키움 로그인 창 띄우기

마스터욱 2023. 3. 29. 00:47
반응형
import sys
import lib as lib

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QAxContainer import *

#import pandas as pd
from pprint import pprint
import re
import requests
from threading import Timer, Thread, Event

import json
from collections import OrderedDict

class perpetualTimer():
def __init__(self, t, hFunction):
self.t = t
self.hFunction = hFunction
self.thread = Timer(self.t, self.handle_function)

def handle_function(self):
self.hFunction()
self.thread = Timer(self.t, self.handle_function)
self.thread.start()

def start(self):
self.thread.start()

def cancel(self):
self.thread.cancel()

class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("뉴스매매(Makeby 욱)")
self.setGeometry(300, 300, 1200, 700)
self.setTable()

self.thread_cnt = 0
self.last_title = ""


print(sys.version)

#키움증권
self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
#print(self.kiwoom)

btn1 = QPushButton("로그인", self)
btn1.move(1000, 20)
btn1.clicked.connect(self.btn1_clicked)

btn2 = QPushButton("상태체크", self)
btn2.move(1100, 20)
btn2.clicked.connect(self.btn2_clicked)

"""""
btn1 = QPushButton("Click me", self)
btn1.move(20, 20)
btn1.clicked.connect(self.btn1_clicked)
"""
def btn1_clicked(self):
#print("로그인 버튼 클릭")
ret = self.kiwoom.dynamicCall("CommConnect()")
print(ret)

def btn2_clicked(self):
if self.kiwoom.dynamicCall("GetConnectState()") == 0:
self.statusBar().showMessage("Not connected")
else:
self.statusBar().showMessage("Connected")

def setTable(self):
#self.setGeometry(5,5,200,200)

newsLabel = QLabel("실시간 뉴스", self)
newsLabel.setGeometry(5, 5, 500, 50)

self.tableWidget = QTableWidget(self)

#self.tableWidget.resize(500, 500)
self.tableWidget.setGeometry(5, 50, 500, 500)

self.tableWidget.setRowCount(20)
self.tableWidget.setColumnCount(2)

#self.tableWidget.setVerticalHeaderLabels(['1','2'])
self.tableWidget.setHorizontalHeaderLabels(['제목', '시간'])

#데이터 넣기
#self.setTableWidgetData()

t = perpetualTimer(2, self.startNews)
t.start()
#self.startNews()

def startNews(self):
self.thread_cnt = self.thread_cnt + 1
print("뉴스 쓰레드 가동(" + str(self.thread_cnt) + ")")
#뉴스 저장하기
self.setNews()
#뉴스 가져오기
self.getNews()

def setTableWidgetData(self):
self.tableWidget.setItem(0, 0, QTableWidgetItem("(0,0)"))
self.tableWidget.setItem(0, 1, QTableWidgetItem("(0,1)"))
self.tableWidget.setItem(1, 0, QTableWidgetItem("(1,0)"))
self.tableWidget.setItem(1, 1, QTableWidgetItem("(1,1)"))

"""
def btn1_clicked(self):
QMessageBox.about(self, "message", "clicked")
"""

#API 서버에서 뉴스크롤링 실행시키기
def setNews2(self):
post_data = {"type":"croll"}
url = "내API 서버주소는 비밀"
r = requests.post(url, data=post_data)
result_json = r.text #{"result":"OK"}

# JSON 디코딩
dict = json.loads(result_json)


#파이썬 자체에서 크롤링
def setNews(self):
#공시정보 가져오기
#lib.get_financial_statements('http://dart.fss.or.kr/api/search.json?auth=5d7fe977e575fb2ec15661d0a1556f40793237f6')
outhtml = lib.get_financial_statements('크롤링 주소는 비밀')
#print(outhtml)
#output = re.match(r'(?s).*<!-- List BBS Block Start -->(.*)<!-- //List BBS Block End -->.*', outhtml, re.M|re.I)
#print(output.group(1))
#output = re.match(r'(?s).*<div class="newListArea">(.*)</div>(.*)</div>.*', output.group(1), re.M|re.I)
output = re.match(r'(?s).*<!-- %%LIST data%% -->(.*)<!-- %%ENDLIST data%% -->.*', outhtml, re.M | re.I)
output_data = ''
if output is not None:
output_data = output.group(1)
#print(output)
else:
print("젠장... 비었음...")

#print(output_data)
outlist = re.split('</tr>', output_data)
#pprint(outlist)

cnt = 0
all_json = OrderedDict()
for row in outlist:
#date = lib.get_between_string(row, '<div id="date_0">', '</div>')
#print(row)
row_list = re.split('<td', row)
#pprint(row_list)
#print(row_list[2])
#print(lib.strip_tags(row_list[3]))
#print(row_list[3])
date = ''
time = ''
title = ''
try:
row_json = OrderedDict()
tmp = re.match(r'(?s).*<div id="date_.*">(.*)</div></td>.*', row_list[1])
date = tmp.group(1)

tmp = re.match(r'(?s).*<div id="time_.*">(.*)</div></td>.*', row_list[2])
time = tmp.group(1)

tmp = re.match(r'(?s).*<div id=\'title_.*\'>(.*)</div></a>.*', row_list[3])
title = tmp.group(1)
title = title.replace('&nbsp; ','')

row_json['date'] = date
row_json['time'] = time
row_json['title'] = title

all_json[str(cnt)] = row_json
except:
'''
print("끝줄에러")
'''

'''
test = ""
test += "date = " + date + " || "
test += "time = " + time + " || "
test += "title = " + title + " || "
print(str(cnt) + " = " + test)
'''
cnt = cnt + 1


#pprint(all_json)
jsonString = json.dumps(all_json)
post_data = {'data': jsonString, "type": "news_toss"}
#print(jsonString)
#pprint(post_data)

#디비에 저장
url = "API 주소는 비밀"
r = requests.post(url, data=post_data)
result_json = r.text #{"result":"OK"}


def getNews(self):
url = "API 주소는 비밀"
r = requests.post(url)
result_json = r.text #{"result":"OK"}

# JSON 디코딩
dict = json.loads(result_json)

# Dictionary 데이타 체크
#print(dict['result'])

#print(dict['list'])
cnt = 0;
#self.tableWidget.setRowCount(20)

for row in dict['list']:
if cnt == 0:
if self.last_title == row['title']:
break
else:
print(row['title'] + " " + row['time'])
self.last_title = row['title']
#for i in range(0, 20):
# self.tableWidget.setItem(i, 0, QTableWidgetItem("1"))
# self.tableWidget.setItem(i, 1, QTableWidgetItem("1"))

title = row['title'][0:40]
self.tableWidget.setItem(cnt, 0, QTableWidgetItem(title))
self.tableWidget.setItem(cnt, 1, QTableWidgetItem(row['time']))

#데이터 갱신을 위해 포커스를 주자
self.tableWidget.setCurrentCell(cnt, 0)
self.tableWidget.setCurrentCell(cnt, 1)
cnt = cnt + 1

#각 열크기 맞춤
self.tableWidget.resizeColumnsToContents()
self.tableWidget.resizeRowsToContents()


if __name__ == "__main__":
app = QApplication(sys.argv)
#print(sys.argv) #D:/project/python/hello/hello.py
myWindow = MyWindow()
myWindow.show()
app.exec_()

 

드디어 키움 로그인창을 띄우는 것까지 성공했습니다.

사실 여기서 무지 삽질을 많이 했습니다.

 

버튼구현후, 테스트 과정에서 버튼을 눌러도 로그인 창이 오픈되지 않는 것이었습니다.

결국 해결방법은 아래의 두가지 조취후 해결되었습니다.

 

1. 키움 Open API 모듈 재설치

2. 파이썬 아나콘다, 파이참 모두 32bit 로 재설치(기존의 64bit 로 설치했었음)

 

구글의 힘으로 겨우 해결했습니다.

삽질의 시간이 길었던만큼 내공도 그만큼 쌓였겠지요?

내일은 키움 클래스를 독립적으로 분리해서 본격적으로 개발을 해보도록 하겠습니다.


이 게시글은
https://webschool.kr/?v=board_view&board_key=30&idx=411
에서 작성한 글입니다. 소스코드의 경우 해당 블로그에서 이뿌게 노출이 되지 않을 수 있사오니, 위 링크로 들어오셔서 보시길 바랍니다.

반응형