#使用的是 pywinauto 0.6.4 和 python3.7.2
# 注意,python3.7.4以上不行的。在github的issue有写
# 在win10_64也是有问题,tree会选错选择
# 向edit控件输入内容,要使用type_keys(""),用set_text失败的。
# 
import pywinauto
from pywinauto import clipboard
from pywinauto import keyboard
from .captcha_recognize import captcha_recognize
import pandas as pd
import io
from .const import BALANCE_CONTROL_ID_GROUP
import time


class THSTrader:

    def __init__(self, exe_path=r"C:\同花顺软件\同花顺\xiadan.exe"): 
        print("正在连接客户端:", exe_path, "......")
        #self.app = pywinauto.Application().start(exe_path)
        try:
            self.app = pywinauto.Application().connect(path=                  exe_path, timeout=10)
        except Exception as ex:
            self.app = pywinauto.Application().start(exe_path)
            time.sleep(2)
            pass
        
        print("连接成功!!!")      
   
        self.main_wnd = self.app.window(title=u"网上股票交易系统5.0")
    
    def buy(self, stock_no, price, amount):
        """ 买入 """
        time.sleep(1)
        self.__select_menu(['买入[F1]'])
        return self.__trade(stock_no, price, amount)

    def sell(self, stock_no, price, amount):
        """ 卖出 """
        time.sleep(1)
        self.__select_menu(['卖出[F2]'])
        return self.__trade(stock_no, price, amount)

    def cancel_entrust(self, entrust_no):
        """ 撤单 """
        time.sleep(1)
        self.__select_menu(['撤单[F3]'])
        cancelable_entrusts = self.__get_grid_data(is_entrust=True)  # 获取可以撤单的条目

        for i, entrust in enumerate(cancelable_entrusts):
            if str(entrust["合同编号"]) == str(entrust_no):  # 对指定合同进行撤单
                return self.__cancel_by_double_click(i)
        return {"success": False, "msg": "没找到指定订单"}

    def get_balance(self):
        """ 获取资金情况 """
        time.sleep(1)
        self.__select_menu(['查询[F4]', '资金股票'])

        result = {}
        for key, control_id in BALANCE_CONTROL_ID_GROUP.items():
            result[key] = float(
                self.main_wnd.window(control_id=control_id, class_name='Static').window_text()
            )
        return result
    
    def check_trade_finished(self, entrust_no):
        """ 判断订单是否完成 """
        time.sleep(1)
        self.__select_menu(['卖出[F2]'])
        time.sleep(1)
        self.__select_menu(['撤单[F3]'])
        cancelable_entrusts = self.__get_grid_data(is_entrust=True)
#        print(cancelable_entrusts)
        for i, entrust in enumerate(cancelable_entrusts):
            if str(entrust["合同编号"]) == str(entrust_no):  # 如果订单未完成,就意味着可以撤单
                if entrust["成交数量"] == 0:
                    return False
        return True
    

    def get_position(self):
        """ 获取持仓 """
        time.sleep(1)
        self.__select_menu(['查询[F4]', '资金股票'])
        return self.__get_grid_data()

    def get_today_entrusts(self):
        """ 获取当日委托 """
        time.sleep(1)
        self.__select_menu(['查询[F4]', '当日委托'])
        return self.__get_grid_data()

    def get_today_trades(self):
        time.sleep(1)
        self.__select_menu(['查询[F4]', '当日成交'])
        return self.__get_grid_data()

    def add_old_user(self,user_item):
        """ 增加账户 """
        #print(self.main_wnd.window(control_id=0x912, class_name="ComboBox").texts())
        """ 开始增加账户 """
        self.main_wnd.window(control_id=0x69B, class_name="Button").click()
        #弹出窗口
        time.sleep(0.3)
        
        #self.main_wnd.window(handle = self.main_wnd.popup_window()).window(control_id=0x3e9, class_name="Edit").type_keys("75084160000")
        popup_window1 = self.main_wnd.window(handle = self.main_wnd.popup_window())
        #combobox 从0开始的。
        
        popup_window1.window(control_id=0x3f3, class_name="ComboBox").select(user_item)
        popup_window1.window(control_id=0x3ee, class_name="Button").click()

        #popup_window1.window(control_id=0x959, class_name="Button").click()        
        #popup_window1.window(handle =popup_window1.popup_window()).print_control_identifiers()     
        #popup_window1.window(handle =popup_window1.popup_window()).window(class_name="CPanel")
        return "ok"

    def __trade(self, stock_no, price, amount):
        #time.sleep(1)
        self.main_wnd.window(control_id=0x3ef, class_name="Button").click()  #重置
        self.main_wnd.window(control_id=0x408, class_name="Edit").wait('ready', 3)  # sometime can't find handle ready, must retry
        self.main_wnd.window(control_id=0x408, class_name="Edit").type_keys(str(stock_no))  # 设置股票代码
        time.sleep(0.3)
        text_len = self.main_wnd.window(control_id=0x409, class_name="Edit").line_length(0)
        for i in range(text_len):
            self.main_wnd.window(control_id=0x409, class_name="Edit").type_keys("{BACKSPACE}") #删除自动获取的价格
        self.main_wnd.window(control_id=0x409, class_name="Edit").type_keys(str(price))  # 设置价格
        self.main_wnd.window(control_id=0x40A, class_name="Edit").type_keys(str(amount))  # 设置股数目
        time.sleep(0.2)
        self.main_wnd.window(control_id=0x3EE, class_name="Button").click()   # 点击卖出or买入
        
        time.sleep(0.2)

        #keyboard.SendKeys("{ENTER}")
        #print(hex(self.app.top_window().handle))#topwindow 不是弹出窗口,要搜索 【下错价格,有提示信息】
        #try:
        #    if "提示信息" in self.main_wnd.window(handle = self.main_wnd.popup_window()).window(control_id=0x555, class_name='Static').window_text():
        #        self.main_wnd.window(handle = self.main_wnd.popup_window()).window(control_id=0x553, class_name='Button').click()
        #except:
        #    pass
        popup_win_hwd = self.main_wnd.popup_window()
        print(hex(popup_win_hwd))
        self.main_wnd.window(handle = popup_win_hwd).window(control_id=0x6, class_name='Button').click()  # 确定买入
        #self.main_wnd.window(handle = popup_win_hwd).set_focus()
        time.sleep(0.3)
        try:
            #在弹出的窗口还是一样的句柄  +0x10000。
            popup_win_hwd = popup_win_hwd+0x10000
            self.main_wnd.window(handle = popup_win_hwd).window(control_id=0x3EC, class_name='Static').wait('ready', 3)
            result = self.main_wnd.window(handle = popup_win_hwd).window(control_id=0x3EC, class_name='Static').window_text()
            self.main_wnd.window(handle = popup_win_hwd).set_focus()
            time.sleep(0.2)
            self.main_wnd.window(handle = popup_win_hwd).window(control_id=0x2, class_name='Button').click()  # 确定
        except:
            return {
                "success": False
            }        
        
        return self.__parse_result(result)

    def __get_grid_data(self, is_entrust=False):
        """ 获取grid里面的数据 """
        time.sleep(0.1)
        grid = self.main_wnd.window(control_id=0x417, class_name='CVirtualGridCtrl')
        time.sleep(0.1)
        grid.set_focus()
        #grid.print_control_identifiers()
        #print(self.main_wnd.PopupMenu.wait('ready').menu().items()) #想获取弹出菜单很难
        #print(hex(grid.PopupMenu.Menu().handle))
        keyboard.SendKeys('^c') #send_keys('^a^c') # select all (Ctrl+A) and copy to clipboard (Ctrl+C)
        data = clipboard.GetData()
        df = pd.read_csv(io.StringIO(data), delimiter='\t', na_filter=False)
        return df.to_dict('records')

    def __select_menu(self, path):
        """ 点击左边菜单 """
        if r"网上股票" not in self.app.top_window().window_text():
            self.app.top_window().set_focus()
            pywinauto.keyboard.SendKeys("{ENTER}")
        self.__get_left_menus_handle().get_item(path).click()

    def __get_left_menus_handle(self):
        while True:
            try:
                handle = self.main_wnd.window(control_id=129, class_name='SysTreeView32')
                handle.wait('ready', 3)  # sometime can't find handle ready, must retry
                return handle
            except Exception as ex:
                print(ex)
                pass

    def __cancel_by_double_click(self, row):
        """ 通过双击撤单 """
        x = 50
        y = 30 + 16 * row
        self.app.top_window().window(control_id=0x417, class_name='CVirtualGridCtrl').double_click(coords=(x, y))
        self.app.top_window().window(control_id=0x6, class_name='Button').click()  # 确定撤单
        time.sleep(0.1)
        if "网上股票交易系统5.0" not in self.app.top_window().window_text():
            result = self.app.top_window().window(control_id=0x3EC, class_name='Static').window_text()
            self.app.top_window().window(control_id=0x2, class_name='Button').click()  # 确定撤单
            return self.__parse_result(result)
        else:
            return {
                "success": True
            }

    @staticmethod
    def __parse_result(result):
        """ 解析买入卖出的结果 """
        
        # "您的买入委托已成功提交,合同编号:865912566。"
        # "您的卖出委托已成功提交,合同编号:865967836。"
        # "您的撤单委托已成功提交,合同编号:865967836。"
        # "系统正在清算中,请稍后重试! "
        
        if r"已成功提交,合同编号:" in result:
            return {
                "success": True,
                "msg": result,
                "entrust_no": result.split("合同编号:")[1].split("。")[0]
            }
        else:
            return {
                "success": False,
                "msg": result
            }


测试的时候发现几个问题,在win10下64位系统,那tree的item会点击错位的。例如想点 市价委托,但是最后点了上面的买入。

# -*- coding: utf-8 -*-
import pywinauto
import time
from pywinauto import application

class AccessDeniedError(Exception):
    """Raise when current user is not an administrator."""
    def __init__(self, arg):
        self.args = arg


class NoExistGroupError(Exception):
    """Raise when group Administrators is not exist."""
    def __init__(self, arg):
        self.args = arg

exe_path =r"C:\同花顺软件\同花顺\xiadan.exe"
print("正在连接客户端:", exe_path, "......")

#app = pywinauto.Application().connect(path=r'C:\同花顺软件\同花顺\xiadan.exe', timeout=10)
app = pywinauto.Application().connect(title_re='网上股票交易系统5.0')
print("连接成功!!!")
if r"网上股票" not in app.top_window().window_text():
     app.top_window().set_focus()
     pywinauto.keyboard.SendKeys("{ENTER}")
     print("设置下单软件为第一界面,handle= ",hex(app.top_window().handle),"text = ",app.top_window().is_dialog())  

#app.window(title=u"网上股票交易系统5.0").print_control_identifiers()

#app.window(title=u"网上股票交易系统5.0").window(best_match='#32770').print_control_identifiers()
app.window(title=u"网上股票交易系统5.0").window(control_id=129, class_name='SysTreeView32').print_control_identifiers()
tree = app.window(title=u"网上股票交易系统5.0").hexin_scroll_wnd2.tree_view
groups = tree.get_item(r'\市价委托\买入')
groups.click()


————————————————
版权声明:本文为CSDN博主「jhui123456」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jhui123456/article/details/104162759

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐