관리자 2 783 0 0

프로토타입 완성했습니다.

삽질 정말 많이 했습니다.

그만큼 소스코드도 정말 더럽습니다.

이쯤하다보니 다음작품은 깔끔하게 짤 자신이 생기네요~

파이썬 응용프로그램 첫 작품 치고는 퀄리티에 만족합니다.

 


 

import sys
import lib as lib
# import kiwoom as ki

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

import webbrowser
from functools import partial

# 미수거래 넣어야 됨

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()
self.thread.cancel()

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.t = perpetualTimer(1, self.startNews)
# self.t.start()

# timer = QTimer()
# timer.timeout.connect(self.startNews)
# timer.start(1000)
self.current_timer = ""
# self.start_timer() # 로그인후 실행하도록 변경

self.start_buy = "NO"
self.start_news = "YES"

# 비동기 방식으로 동작되는 이벤트를 동기화(순서대로 동작) 시킬 때
self.orderLoop = None
self.requestLoop = None
self.loginLoop = None

self.apiUrl = "내 API 주소는 비밀"

self.thread_cnt = 0
self.last_title = ""

# 키움개인정보
# self.user_id = "dev84" # 테스트
self.user_id = ""
self.account_number = "" # 키움계좌

# print(sys.version)

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

# 키움 이벤트 등록(시그널과 슬롯을 연결)
self.kiwoom.OnEventConnect.connect(self.event_connect) # 개인정보 호출됨
self.kiwoom.OnReceiveChejanData.connect(self.receive_chejan_data) # 매수체결후 호출됨
self.kiwoom.OnReceiveTrData.connect(self.receive_trdata) # 이 섹히가 범인이었음
self.kiwoom.OnReceiveMsg.connect(self.receive_msg) # 매수시도후 에러발생시

# print("매수테스트 시작")
# 8102230011
# 8102-2300
'''
로그인 후 테스트 해야함
returnCode = self.kiwoom.dynamicCall("SendOrder(QString, QString, QString, int, QString, int, int, QString, QString)", ["auto_buy", "4989", "8102-2300", 10, "034220", 3, "", "03", ""])
if returnCode != 0:
# print("매수결과 = " + str(returnCode))
KiwoomProcessingError("sendOrder() : " + ReturnCode.CAUSE[returnCode])
else:
print("매수성공 끼야호!")
'''

self.textLabel = QLabel("정보 : ", self)
self.textLabel.setGeometry(510, 20, 500, 20)

self.btn_test = QPushButton("자동매수시작", self)
self.btn_test.move(900, 20)
# btn_test.clicked.connect(ki_instance.btn1_clicked)
self.btn_test.clicked.connect(self.test_buy)
'''
self.btn_test = Button(text="자동매수시작", width=100, height=20, command=self.test_buy)
# self.btn_test.move(900, 20)
self.btn_test.place(x=900,y=20)
self.btn_test.pack()
'''

'''
self.btn_test2 = QPushButton("매수테스트", self)
self.btn_test2.move(700, 20)
# btn_test.clicked.connect(ki_instance.btn1_clicked)
self.btn_test2.clicked.connect(self.test_buy2)
'''


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

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

'''
self.ed = QLineEdit()
self.ed.move(700, 50)
self.ed.setText("홍길동") # 텍스트 쓰기
text = self.ed.text() # 텍스트 읽기
self.ed.setPlaceholderText("이름을 입력하시오") # Watermark로 텍스트 표시
self.ed.selectAll() # 텍스트 모두 선택
# ed.setReadOnly(True)# 에디트는 읽기 전용으로
# e.setEchoMode(QLineEdit.Password)# Password 스타일 에디트
'''
keywordLabel = QLabel("종목&키워드 매칭(종목코드:키워드1,키워드2,키워드3...)", self)
keywordLabel.setGeometry(510, 50, 500, 50)

self.keywordbtn = QPushButton("매칭 저장", self)
self.keywordbtn.move(1100, 60)
self.keywordbtn.clicked.connect(self.keywordbtn_clicked)

self.textEdit = QTextEdit(self)
self.textEdit.resize(670, 250)
self.textEdit.move(510, 100)

logLabel = QLabel("로그", self)
logLabel.setGeometry(510, 370, 500, 50)

self.textEdit2 = QTextEdit(self)
self.textEdit2.resize(670, 250)
self.textEdit2.move(510, 420)
# self.textEdit2.setReadOnly(True)

"""""
btn1 = QPushButton("Click me", self)
btn1.move(20, 20)
btn1.clicked.connect(self.btn1_clicked)
"""

def start_timer(self):
if self.current_timer:
self.current_timer.stop()
self.current_timer.deleteLater()

self.current_timer = QTimer()
self.current_timer.timeout.connect(self.startNews)
self.current_timer.setSingleShot(True)
self.current_timer.start(1000)

def keywordbtn_clicked(self):
if self.user_id == "":
QMessageBox.warning(self, "로그인 해줘용", "로그인 좀 해줘용 (o^3^)o~")
else:
# print("저장")
content = self.textEdit.toPlainText()
# print(content)
# print(self.user_id)

post_data = {"type": "keyword_save", "stock_id": self.user_id, "content": content}
r = requests.post(self.apiUrl, data=post_data)
result_json = r.text # {"result":"OK"}
# print(result_json)

# JSON 디코딩
dict = json.loads(result_json)
# print("result = " + dict['result']) # OK
if dict['result'] == "OK":
w = QWidget() # The QWidget widget is the base class
w.setWindowTitle('키워드저장버튼')
w.resize(400, 200)
result = QMessageBox.information(w, "Information", "저장완료")

# if result == QMessageBox.Ok:
# myTextbox.setText("Clicked OK on Information.")

def btn1_clicked(self):
if self.user_id == "":
# print("로그인 버튼 클릭")
ret = self.kiwoom.dynamicCall("CommConnect()")
self.loginLoop = QEventLoop()
self.loginLoop.exec_()
if ret == 0:
self.statusBar().showMessage("로그인 창 열기 성공")
# self.btn1.setText('로그인 정보보기')
# self.getLoginInfo()
else:
self.statusBar().showMessage("로그인 창 열기 실패")
# print(ret)
else:
QMessageBox.warning(self, "이미 당신은", "로그인 상태입니다.")

def btn1_clicked_logined(self):
print("ok")

# 로그인 상태 확인
def btn2_clicked(self):
if self.kiwoom.dynamicCall("GetConnectState()") == 0:
self.statusBar().showMessage("Not connected")
else:
self.statusBar().showMessage("Connected")

# 로그인 유저 정보 호출
def getLoginInfo(self, type):
# print("getLoginInfo")
info = self.kiwoom.dynamicCall("GetLoginInfo(QString)", type)
# print(info)
return info

def get_stock_info(self, code):
# print("get_stock_info Code = " + code)

# SetInputValue
self.kiwoom.dynamicCall("SetInputValue(QString, QString)", "종목코드", code)

# CommRqData
# 구분자 : opt10001
# 스프릿 : opt10001_req
self.kiwoom.dynamicCall("CommRqData(QString, QString, int, QString)", "opt10001_req__WOOK__" + code, "opt10001", 0, "0101")
self.requestLoop = QEventLoop()
self.requestLoop.exec_()

# 매수테스트
# Process finished with exit code -1073740791 (0xC0000409)
def test_buy2(self):
code = "003550";
temp = re.split(';', self.account_number)
buy_account_number = temp[0]

'''
if not (isinstance(buy_account_number, str) and isinstance(code, str)):
print("으악 스트링이 아냐!")
'''

returnCode = self.kiwoom.dynamicCall(
"SendOrder(QString, QString, QString, int, QString, int, int, QString, QString)",
["auto_buy", "4989", buy_account_number, 1, code, 1, "", "03", ""])

if returnCode != 0:
# print("매수결과 = " + str(returnCode))
KiwoomProcessingError("sendOrder : " + ReturnCode.CAUSE[returnCode])
else:
# self.start_news = "NO"
msg = "매수성공, 종목코드 = " + code + ", 계좌번호 = " + buy_account_number
print(msg)
content = self.textEdit2.toPlainText()
self.textEdit2.setText(msg + "\n" + content)

# 주문이벤트 루프 시작
self.orderLoop = QEventLoop()
self.orderLoop.exec_()

# 자동매수시작
def test_buy(self):
if self.start_buy == "OK":
QMessageBox.warning(self, "이미 눌렀음", "이미 자동매수 실행중입니다.")
else:
#print("test_buy called")
if self.user_id == "":
# tkinter.messagebox.askyesnocancel("로그인 해줘용", "자동매수를 위해서는 로그인이 필요합니다.\n\n로그인후 우측하단의 매수비밀번호 설정을 꼭! 해주세요~")
# mb.showerror("로그인 해줘용", "자동매수를 위해서는 로그인이 필요합니다.\n\n로그인후 우측하단의 매수비밀번호 설정을 꼭! 해주세요~")
QMessageBox.warning(self, "로그인 해줘용", "자동매수를 위해서는 로그인이 필요합니다.\n\n로그인후 우측하단의 매수비밀번호 설정을 꼭! 해주세요~")
else:
# res = mb.askyesnocancel("자동매수시작", "우측하단의 매수비밀번호를 입력하셨습니까?\n자동매수를 시작하시겠습니까?")
choice = QMessageBox.question(self, "매수비밀번호 넣었나열?", "우측하단의 매수비밀번호를 꼭 입력해야만 자동매수가 정상작동합니다.\n자동매수를 시작하시겠습니까?", QMessageBox.Yes | QMessageBox.No)
if choice == QMessageBox.Yes:
self.start_buy = "OK"
else:
pass

def receive_trdata(self, screen_no, rqname, trcode, recordname, prev_next, data_len, err_code, msg1, msg2):
# screen_no = 4989, rqname = auto_buy, trcode = KOA_NORMAL_BUY_KP_ORD,prev_next = , data_len = 0, err_code = , msg1 = , msg2 =
print("receive_trdata 호출됨, screen_no = " + str(screen_no) + ", rqname = " + str(rqname) + ", trcode = " + str(trcode) + ",prev_next = " + str(prev_next) + ", data_len = " + str(data_len) + ", err_code = " + str(err_code) + ", msg1 = " + str(msg1) + ", msg2 = " + str(msg2))

rqname_split = re.split('__WOOK__', rqname)
rqname = rqname_split[0]
code = rqname_split[1]

print("====================================")
print("receive_trdata 호출됨, rqname = " + rqname + ", code = " + code)

if rqname == "opt10001_req":
name = self.kiwoom.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "종목명")
volume = self.kiwoom.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "거래량")
now_price = self.kiwoom.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "현재가")

# strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("종목코드")); strData.Trim();
# strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("거래량")); strData.Trim();
# strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("시가")); strData.Trim();
# strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("고가")); strData.Trim();
# strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("저가")); strData.Trim();
# strData = OpenAPI.GetCommData(sTrcode, strRQName, nIdx, _T("현재가")); strData.Trim();

print("====================================")
print("종목코드 : " + code)
print("종목명 : " + name.strip())
print("거래량 : " + volume.strip())
print("현재가 : " + now_price.strip())

# 여기서 매수하자
n_price = abs(int(now_price.strip()))

# self.account_number = self.account_number.replace(';', '')
temp = re.split(';', self.account_number)
buy_account_number = temp[0]

print("buy_account_number = " + buy_account_number)
print("n_price = " + str(n_price))

returnCode = self.kiwoom.dynamicCall(
"SendOrder(QString, QString, QString, int, QString, int, int, QString, QString)",
["auto_buy__WOOK__" + code, "4989", buy_account_number, 1, code, 1, "", "03", ""])
# 주문이벤트 루프 시작
self.orderLoop = QEventLoop()
self.orderLoop.exec_()

if returnCode != 0:
# print("매수결과 = " + str(returnCode))
KiwoomProcessingError("sendOrder : " + ReturnCode.CAUSE[returnCode])
else:
# self.start_news = "NO"
msg = "매수성공, 종목코드 = " + code + ", 계좌번호 = " + buy_account_number
print(msg)
content = self.textEdit2.toPlainText()
self.textEdit2.setText(msg + "\n" + content)

'''
try:
self.requestLoop.exit()
except AttributeError:
pass
'''

'''
[SendOrder() 함수]

SendOrder(
BSTR sRQName, // 사용자 구분명
BSTR sScreenNo, // 화면번호
BSTR sAccNo, // 계좌번호 10자리
LONG nOrderType, // 주문유형 1:신규매수, 2:신규매도 3:매수취소, 4:매도취소, 5:매수정정, 6:매도정정
BSTR sCode, // 종목코드
LONG nQty, // 주문수량
LONG nPrice, // 주문가격
BSTR sHogaGb, // 거래구분(혹은 호가구분)은 아래 참고
BSTR sOrgOrderNo // 원주문번호입니다. 신규주문에는 공백, 정정(취소)주문할 원주문번호를 입력합니다.
)

9개 인자값을 가진 국내 주식주문 함수이며 리턴값이 0이면 성공이며 나머지는 에러입니다.
1초에 5회만 주문가능하며 그 이상 주문요청하면 에러 -308을 리턴합니다.

[거래구분]
모의투자에서는 지정가 주문과 시장가 주문만 가능합니다.

00 : 지정가
03 : 시장가
05 : 조건부지정가
06 : 최유리지정가
07 : 최우선지정가
10 : 지정가IOC
13 : 시장가IOC
16 : 최유리IOC
20 : 지정가FOK
23 : 시장가FOK
26 : 최유리FOK
61 : 장전시간외종가
62 : 시간외단일가매매
81 : 장후시간외종가
'''


# 로그인 후 실행되는 함수
# 로그인성공
def event_connect(self, code):
if code == 0:
self.statusBar().showMessage("로그인 성공")
self.user_id = self.getLoginInfo("USER_ID")
self.account_number = self.getLoginInfo("ACCNO")
# print(self.account_number)

self.textLabel.setText("●계좌번호 : " + self.account_number)
self.btn1.setText(self.user_id + "님")
# 버튼 이벤트 해제해야 하는데 일단 스킵

# 종목코드:키워드 정보 가져오기
post_data = {"type": "get_keyword", "stock_id": self.user_id}
r = requests.post(self.apiUrl, data=post_data)
result_json = r.text # {"result":"OK"}

# JSON 디코딩
dict = json.loads(result_json)
data = dict['data']
# print("종목키워드 데이터\n=================\n" + data + "\n=================\n")
self.textEdit.setText(data)

# 매수테스트
'''
종목코드 : 003550
종목명 : LG
거래량 : 42202
현재가 : 86000
account_number = 8102230011
8739688531
n_price = 86000
'''

'''
print("로그인 후 매수테스트")
returnCode = self.kiwoom.dynamicCall(
"SendOrder(QString, QString, QString, int, QString, int, int, QString, QString)",
["auto_buy", "4989", "8102230011", 1, "034220", 10, "", "03", ""])
if returnCode != 0:
# print("매수결과 = " + str(returnCode))
KiwoomProcessingError("sendOrder : " + ReturnCode.CAUSE[returnCode])
else:
print("매수성공 끼야호!")
'''

self.start_timer()
else:
self.statusBar().showMessage("로그인 실패")

try:
self.loginLoop.exit()
except AttributeError:
pass

# print("event_connect 호출됨")
# self.event_connect_loop.exit()

# SendOrder(주문) 성공후 호출
'''
[OnReceiveChejanData() 이벤트]

OnReceiveChejanData(
BSTR sGubun, // 체결구분 접수와 체결시 '0'값, 국내주식 잔고전달은 '1'값, 파생잔고 전달은 '4'
LONG nItemCnt,
BSTR sFIdList
)

주문요청후 주문접수, 체결통보, 잔고통보를 수신할 때 마다 호출되며 GetChejanData()함수를 이용해서 상세한 정보를 얻을수 있습니다.
'''
def receive_chejan_data(self, gubun, item_cnt, field_list):
print("receive_chejan_data 호출")
# print("receive_chejan_data 호출, 매수성공, gubun = " + gubun + " , item_cnt = " + str(item_cnt) + " , field_list = " + field_list)
# print(self.get_chejan_data(9203))
# print(self.get_chejan_data(302))
# print(self.get_chejan_data(900))
# print(self.get_chejan_data(901))

# 매수성공(일단 사용안함)
def get_chejan_data(self, fid):
ret = self.dynamicCall("GetChejanData(int)", fid)
return ret

# 매수후메세지리턴(성공이든 실패든 호출한다)
def receive_msg(self, scr_no, rq_name, tr_code, msg):
print("receive_msg 호출됨, scr_no = " + scr_no + ", rq_name = " + rq_name + ", tr_code = " + tr_code + ", msg = " + msg)
try:
self.orderLoop.exit()
except AttributeError:
pass

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(3)

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

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

def startNews(self):
self.thread_cnt = self.thread_cnt + 1
print("뉴스 쓰레드 가동(" + str(self.thread_cnt) + ")")

# 뉴스 쓰레드 가동(283) 에서
# Process finished with exit code -1073740940 (0xC0000374) 에러발생
# Process finished with exit code -1073741819 (0xC0000005)
# Process finished with exit code -1073741819 (0xC0000005)

# 뉴스 저장하기
# self.setNews2()

# 뉴스 가져오기
# self.get_news()

# 뉴스 쓰레드 가동(281) 에서
# Process finished with exit code -1073740940 (0xC0000374)
self.get_set_news()

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

# timer = QTimer()
# timer.timeout.connect(self.startNews)
# timer.start(1000)

if self.start_news == "YES":
self.start_timer()

'''
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 get_set_news(self):
post_data = {"type": "getset", "stock_id": self.user_id}
r = requests.post(self.apiUrl, data=post_data)
result_json = r.text # {"result":"OK"}

# JSON 디코딩
dict = json.loads(result_json)
# print("get_set_news = " + dict['result'])

# 매칭된 키워드가 있으면 로그로 보여주기
'''
뉴스 쓰레드 가동(135)
{'111': ['(주)', '결과']}
'''
if dict['log_text']:
content = self.textEdit2.toPlainText()
self.textEdit2.setText(dict['log_text'] + content)

# print(dict['list'])
# print(dict['buy_code'])
# for i in dict['buy_code']:
# print("구매종목코드 : " + i)
'''
003550 : LG
034220 : LG디스플레이
001120 : LG상사
'''
if self.start_buy == "OK":
buy_code = re.split(',', dict['buy_code'])
for row in buy_code:
if row:
# print("구매종목코드 : " + row)
self.get_stock_info(row)

# 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:30]
self.tableWidget.setItem(cnt, 0, QTableWidgetItem(title))
self.tableWidget.setItem(cnt, 1, QTableWidgetItem(row['time']))

detailbtn = QPushButton("보기")
# detailbtn.clicked.connect(lambda:self.detailbtn_clicked(row['idx']))
detailbtn.clicked.connect(partial(self.detailbtn_clicked, row['idx']))
self.tableWidget.setCellWidget(cnt, 2, detailbtn)
# print(row['idx'])

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

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

# 기사 상세보기 띄우기
def detailbtn_clicked(self, idx):
# print(idx)
url = self.apiUrl + "?type=news_detail&idx=" + idx + "&stock_id=" + self.user_id
webbrowser.open(url)

# API 서버에서 뉴스크롤링 실행시키기
def setNews2(self):
post_data = {"type": "set", "stock_id": self.user_id}
r = requests.post(self.apiUrl, data=post_data)
result_json = r.text # {"result":"OK"}

# JSON 디코딩
dict = json.loads(result_json)
print("setNews2 = " + dict['result'])

# 파이썬 자체에서 크롤링
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])
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", "stock_id": self.user_id}
# print(jsonString)
# pprint(post_data)

# 디비에 저장
r = requests.post(self.apiUrl, data=post_data)
result_json = r.text # {"result":"OK"}

def get_news(self):
post_data = {"type": "get", "stock_id": self.user_id}
r = requests.post(self.apiUrl, data=post_data)
result_json = r.text # {"result":"OK"}
# print("result_json = " + result_json)

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

# Dictionary 데이타 체크
print("get_news = " + 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()


class KiwoomProcessingError(Exception):
""" 키움에서 처리실패에 관련된 리턴코드를 받았을 경우 발생하는 예외 """

def __init__(self, msg="처리 실패"):
# self.msg = msg
print(msg)

def __str__(self):
return self.msg

def __repr__(self):
return self.msg

class ReturnCode(object):
""" 키움 OpenApi+ 함수들이 반환하는 값 """

OP_ERR_NONE = 0 # 정상처리
OP_ERR_FAIL = -10 # 실패
OP_ERR_LOGIN = -100 # 사용자정보교환실패
OP_ERR_CONNECT = -101 # 서버접속실패
OP_ERR_VERSION = -102 # 버전처리실패
OP_ERR_FIREWALL = -103 # 개인방화벽실패
OP_ERR_MEMORY = -104 # 메모리보호실패
OP_ERR_INPUT = -105 # 함수입력값오류
OP_ERR_SOCKET_CLOSED = -106 # 통신연결종료
OP_ERR_SISE_OVERFLOW = -200 # 시세조회과부하
OP_ERR_RQ_STRUCT_FAIL = -201 # 전문작성초기화실패
OP_ERR_RQ_STRING_FAIL = -202 # 전문작성입력값오류
OP_ERR_NO_DATA = -203 # 데이터없음
OP_ERR_OVER_MAX_DATA = -204 # 조회가능한종목수초과
OP_ERR_DATA_RCV_FAIL = -205 # 데이터수신실패
OP_ERR_OVER_MAX_FID = -206 # 조회가능한FID수초과
OP_ERR_REAL_CANCEL = -207 # 실시간해제오류
OP_ERR_ORD_WRONG_INPUT = -300 # 입력값오류
OP_ERR_ORD_WRONG_ACCTNO = -301 # 계좌비밀번호없음
OP_ERR_OTHER_ACC_USE = -302 # 타인계좌사용오류
OP_ERR_MIS_2BILL_EXC = -303 # 주문가격이20억원을초과
OP_ERR_MIS_5BILL_EXC = -304 # 주문가격이50억원을초과
OP_ERR_MIS_1PER_EXC = -305 # 주문수량이총발행주수의1%초과오류
OP_ERR_MIS_3PER_EXC = -306 # 주문수량이총발행주수의3%초과오류
OP_ERR_SEND_FAIL = -307 # 주문전송실패
OP_ERR_ORD_OVERFLOW = -308 # 주문전송과부하
OP_ERR_MIS_300CNT_EXC = -309 # 주문수량300계약초과
OP_ERR_MIS_500CNT_EXC = -310 # 주문수량500계약초과
OP_ERR_ORD_WRONG_ACCTINFO = -340 # 계좌정보없음
OP_ERR_ORD_SYMCODE_EMPTY = -500 # 종목코드없음

CAUSE = {
0: '정상처리',
-10: '실패',
-100: '사용자정보교환실패',
-102: '버전처리실패',
-103: '개인방화벽실패',
-104: '메모리보호실패',
-105: '함수입력값오류',
-106: '통신연결종료',
-200: '시세조회과부하',
-201: '전문작성초기화실패',
-202: '전문작성입력값오류',
-203: '데이터없음',
-204: '조회가능한종목수초과',
-205: '데이터수신실패',
-206: '조회가능한FID수초과',
-207: '실시간해제오류',
-300: '입력값오류',
-301: '계좌비밀번호없음',
-302: '타인계좌사용오류',
-303: '주문가격이20억원을초과',
-304: '주문가격이50억원을초과',
-305: '주문수량이총발행주수의1%초과오류',
-306: '주문수량이총발행주수의3%초과오류',
-307: '주문전송실패',
-308: '주문전송과부하',
-309: '주문수량300계약초과',
-310: '주문수량500계약초과',
-340: '계좌정보없음',
-500: '종목코드없음'
}

if __name__ == "__main__":
app = QApplication(sys.argv)
myWindow = MyWindow()
myWindow.show()
app.exec_()

Comments [2]

비회원
저런 폼 형식은 어떻게 구성하는지 알 수 있을까요?
10 마스터욱
답변      추천 
질문의 범위가 애매해서 어떻게 답변드리기가 어렵네요...
저 작품은 파이큐티를 사용하지 않고, 순수 날코딩으로 그린 작품입니다.
일일이 좌표값 하나씩 다 줘가면서요~

제목 글쓴이
파이썬 공시뉴스 자동매매 프로그램 ver2.0 댓글 11 관리자
키움API, 나의 매수리스트 불러오기 관리자
Qt Designer XML 을 py 소스로 변경작업   관리자
관리종목 필터링 추가 관리자
파이썬 뉴스 자동매매, 매수리스트 완료 관리자
뉴스자동매매, 매수로직 적용완료 관리자
실시간 뉴스, 종목 키워드, 주문 설정, 매수 패턴 적용완료 관리자
종목코드 데이터베이스에 저장 관리자
파이썬을 이용한 뉴스매매 ver2.0 실시간 뉴스 + 주문설정 페이지 제작완료 관리자
키움 API를 이용한 뉴스매매 ver2.0 개발시작 관리자
최종 완성본 이라기보다는 일단 프로토타입 완성 댓글 2 관리자
매수성공 관리자
매수 API가 안되길래 키움증권에 문의남김2. 관리자
매수 API가 안되길래 키움증권에 문의남김. 관리자
공시뉴스기사와 키워드 매칭작업 관리자
공시뉴스 초단위로 불러오기, 쓰레드 문제 해결 관리자
키움 로그인 창 띄우기 댓글 1 관리자
개발에 도움받은 페이지 목록 관리자
뉴스 크롤링 완료 관리자
파이참(PyCharm) 설치 관리자