python办公自动化系列之金蝶K3自动登录(二)

博客 动态
0 288
羽尘
羽尘 2022-02-10 18:55:11
悬赏:0 积分 收藏

python办公自动化系列之金蝶K3自动登录(二)

  接上一篇博文python办公自动化系列之金蝶K3自动登录(一),我们接着聊聊利用python脚本实现金蝶K3 Wise客户端自动登录这一需求。

 

 

   如上图所示,自动选择【组织机构】后,我们还需要驱动【当前账套】、【命名用户身份登录】、【用户名】、【密码】、【确定】这几个控件,才算是完成了K3 UI自动化的第一步:自动登录。

一、设置【当前账套】控件

  【当前账套】Label右边对应的同样是一个ThunderRT6ComboBox 类,我们选择comboBox某个下拉项时,只有基于索引Index,但是由于集团公司随着业务不断变化,账套数可能存在变化,每个公司账套对应的索引值也会变化。因此,我们最好想办法实现基于账套名称来实现驱动某个comboBox控件。比较通俗易懂的做法是,我们先设法拿到这个组件的所有listItem,将每个Item对应的value(文本值)和listIndex(索引)存入一个字典,那么当用户端随便抛给我们一个账套名时,我们便能基于该字典迅速知道listIndex,再基于它来选择这个comboBox控件。这里面涉及到comboBox一些属性和方法的应用,具体示例代码如下:

 1 import win32gui,win32con 2 def getAccountDic(currentAccountHwnd): 3     '''根据【当前账套】的句柄,得到该comboBox所有下拉选项,将选项值ItemText和对应的ItemIndex存入字典 accountDic,最终返回''' 4     accountDic={} 5     accountCnt=win32gui.SendMessage(currentAccountHwnd, win32con.CB_GETCOUNT, 0, 0) 6     for i in range(accountCnt): 7         textLen= win32gui.SendMessage(currentAccountHwnd, win32con.CB_GETLBTEXTLEN, i,0)*2 # 创建一个比combobox 文本长度两倍的buffer,确保数据都能存进去 8         buffer = win32gui.PyMakeBuffer(textLen) 9         win32gui.SendMessage(currentAccountHwnd, win32con.CB_GETLBTEXT, i, buffer)10         address,length=win32gui.PyGetBufferAddressAndLen(buffer[:-1])11         length=int((length+1)/2) 12         itemText=win32gui.PyGetString(address,length).strip()  # 从内存中取出combobox的当前项内容  13         accountDic[itemText]=i14     return accountDic15 16 def setCurrentAccount(currentAccountHwnd,currentAccountName,accountDic):17     '''根据【当前账套】的句柄,,需要选择的账套名称,和账套字典,选择特定账套为当前账套'''18     accountIndex=accountDic[currentAccountName]19     win32gui.SendMessage(currentAccountHwnd, win32con.CB_SETCURSEL, accountIndex, 0)

 

二、选择【登录方式】为【以命名用户身份登录(D)】

  根据实际需要,小爬这里演示下以命名用户身份登录(D),其它登录方式,手段同理。spy++观察到它其实是一个optionButton。我们可以这样设置:

1 def setOptionBtn(parentHwnd,optionName):2     # optionName="以命名用户身份登录(D)"3     '''通过spy++得到这些optionButton的父元素句柄,在基于文本optionName找到并选择特定的optionButton'''4     optionBtnHandle=win32gui.FindWindowEx(parentHwnd,0,None, optionName) # 以命名用户身份登录(D) optionButton5     win32gui.SendMessage(optionBtnHandle, win32con.WM_LBUTTONDOWN, 0, 0) # 设置登录方式为【以命名用户身份登录(D)】6     time.sleep(0.01)7     win32gui.SendMessage(optionBtnHandle, win32con.WM_LBUTTONUP, 0, 0)

 

三、设置【用户名】、【密码】控件

 

 

 

  通过spy++观察到这两个控件的类名为ThunderRT6TextBox,也算是textBox的子类。我们可以大胆使用SendMessage的WM_SETTEXT来实现这一点,唯一的难度在于基于类名来定位这两个控件时稍微有些麻烦,其中【密码框】控件可以通过定位父元素,然后利用findwindowEx方法,基于ThunderRT6TextBox找到第一个元素即可,而【用户名框】可以通过【当前账套】控件来找下一个控件得到。这里比较让人混淆的是:后台的所有控件【用户名】在下,【密码】在上,与肉眼观察到的物理位置刚好相反。具体代码示例如下:

1 def setUserInfo(userName,passWord,parentHwnd,currentAccountHwnd):2     passwordHwnd=win32gui.FindWindowEx(parentHwnd,0,"ThunderRT6TextBox", None) # 密码框,基于父元素和其类名找到的第一个即可3     time.sleep(0.1)4     userNameHwnd=win32gui.FindWindowEx(parentHwnd,currentAccountHwnd,None, None)  # 用户名框,基于【当前账套】控件句柄找到下一个即可5     time.sleep(0.1)6     win32gui.SendMessage(userNameHwnd, win32con.WM_SETTEXT, None,userName)7     time.sleep(0.1)8     win32gui.SendMessage(passwordHwnd, win32con.WM_SETTEXT, None,passWord)

四、发送【回车】实现登录

  小爬通过模拟给登陆界面发送【回车键】来实现登录,示例代码如下:

1     '''根据登陆界面句柄sysLoginWnd,发送回车键实现登录'''2     win32gui.PostMessage(sysLoginWnd, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)3     time.sleep(0.01)4     win32gui.PostMessage(sysLoginWnd, win32con.WM_KEYUP, win32con.VK_RETURN, 0)

   结合上一篇博文,我们基本就完成了K3登录需要的各个方法,我们只需要依次调用,就可以实现K3自动登录某个账套啦。希望小爬的分享对你们的日常工作有所帮助,完整代码如下,供参考,:

 1 # 需要使用管理员权限运行VScode或者Pycharm,否则无法正常使用 2 import win32gui,win32api,win32con,subprocess,time,os 3 def getK3LoginHwnd(): 4     sysLoginWnd=win32gui.FindWindow('ThunderRT6Form',"金蝶K/3系统登录") # K3系统登录窗 5     if sysLoginWnd==0: 6         subprocess.Popen(r'C:\Program Files (x86)\Kingdee\K3ERP\K3MainNet.exe') 7  8     # subprocess发送指令启动后需要等K3登录窗彻底可见后,再进行后续操作 9     while sysLoginWnd==0:10         time.sleep(0.3)11         sysLoginWnd=win32gui.FindWindow('ThunderRT6Form',"金蝶K/3系统登录") # K3系统登录窗12     isSysLoginWndVisible=013     while isSysLoginWndVisible==0:14         time.sleep(0.3)15         sysLoginWnd=win32gui.FindWindow('ThunderRT6Form',"金蝶K/3系统登录") # K3系统登录窗16         isSysLoginWndVisible=win32gui.IsWindowVisible(sysLoginWnd) # 判断窗口是否已经对用户可见17     return sysLoginWnd18  19 def setOrganization(sysLoginWnd,organizationIndex):20     '''根据K3登录窗的句柄sysLoginWnd和下拉框索引值organizationIndex,选择特定的组织机构'''21     mainHwnd1=win32gui.FindWindowEx(sysLoginWnd,0,None, '') # ThunderRT6PictureBoxDC22     mainHwnd2=win32gui.FindWindowEx(sysLoginWnd,mainHwnd1,None, '') # ThunderRT6PictureBoxDC23     organizationHwnd=win32gui.FindWindowEx(mainHwnd2,0,"ThunderRT6ComboBox", '') # 组织机构24     currentOrgIndex=win32gui.SendMessage(organizationHwnd, win32con.CB_GETCURSEL) # 当前combobox选中的index25     if currentOrgIndex!=organizationIndex:26         win32gui.SendMessage(organizationHwnd, win32con.CB_SETCURSEL, organizationIndex, 0)27 28         '''模拟鼠标左键点击元素,激活它'''29         win32gui.SendMessage(organizationHwnd, win32con.WM_LBUTTONDOWN, 0, 0) 30         time.sleep(0.01)31         win32gui.SendMessage(organizationHwnd, win32con.WM_LBUTTONUP, 0, 0)32 33         '''小爬此处的场景中,【组织机构】有6个下拉项,那么最大的index就是5'''34         if organizationIndex<5: # 模拟键盘↓+键盘↑35             win32gui.PostMessage(organizationHwnd, win32con.WM_KEYDOWN, win32con.VK_DOWN, 0)36             time.sleep(0.01)37             win32gui.PostMessage(organizationHwnd, win32con.WM_KEYUP, win32con.VK_DOWN, 0)38             time.sleep(0.1)39             win32gui.PostMessage(organizationHwnd, win32con.WM_KEYDOWN, win32con.VK_UP, 0)40             time.sleep(0.01)41             win32gui.PostMessage(organizationHwnd, win32con.WM_KEYUP, win32con.VK_UP, 0)42         else: # 模拟键盘↑+键盘↓43             win32gui.PostMessage(organizationHwnd, win32con.WM_KEYDOWN, win32con.VK_UP, 0)44             time.sleep(0.01)45             win32gui.PostMessage(organizationHwnd, win32con.WM_KEYUP, win32con.VK_UP, 0) 46             time.sleep(0.1) 47             win32gui.PostMessage(organizationHwnd, win32con.WM_KEYDOWN, win32con.VK_DOWN, 0)48             time.sleep(0.01)49             win32gui.PostMessage(organizationHwnd, win32con.WM_KEYUP, win32con.VK_DOWN, 0)50             time.sleep(0.1)51          52 def getAccountDic(currentAccountHwnd):53     '''根据【当前账套】的句柄,得到该comboBox所有下拉选项,将选项值ItemText和对应的ItemIndex存入字典 accountDic,最终返回'''54     accountDic={}55     accountCnt=win32gui.SendMessage(currentAccountHwnd, win32con.CB_GETCOUNT, 0, 0)56     for i in range(accountCnt):57         textLen= win32gui.SendMessage(currentAccountHwnd, win32con.CB_GETLBTEXTLEN, i,0)*2 # 创建一个比combobox 文本长度两倍的buffer,确保数据都能存进去58         buffer = win32gui.PyMakeBuffer(textLen)59         win32gui.SendMessage(currentAccountHwnd, win32con.CB_GETLBTEXT, i, buffer)60         address,length=win32gui.PyGetBufferAddressAndLen(buffer[:-1])61         length=int((length+1)/2) 62         itemText=win32gui.PyGetString(address,length).strip()  # 从内存中取出combobox的当前项内容  63         accountDic[itemText]=i64     return accountDic65 66 def setCurrentAccount(currentAccountHwnd,currentAccountName,accountDic):67     '''根据【当前账套】的句柄,,需要选择的账套名称,和账套字典,选择特定账套为当前账套'''68     accountIndex=accountDic[currentAccountName]69     win32gui.SendMessage(currentAccountHwnd, win32con.CB_SETCURSEL, accountIndex, 0)70 71 def setOptionBtn(parentHwnd,optionName):72     # optionName="以命名用户身份登录(D)"73     '''通过spy++得到这些optionButton的父元素句柄,在基于文本optionName找到并选择特定的optionButton'''74     optionBtnHandle=win32gui.FindWindowEx(parentHwnd,0,None, optionName) # 以命名用户身份登录(D) optionButton75     win32gui.SendMessage(optionBtnHandle, win32con.WM_LBUTTONDOWN, 0, 0) # 设置登录方式为【以命名用户身份登录(D)】76     time.sleep(0.01)77     win32gui.SendMessage(optionBtnHandle, win32con.WM_LBUTTONUP, 0, 0)78 79 def setUserInfo(userName,passWord,parentHwnd,currentAccountHwnd):80     passwordHwnd=win32gui.FindWindowEx(parentHwnd,0,"ThunderRT6TextBox", None) # 密码框,基于父元素和其类名找到的第一个即可81     time.sleep(0.1)82     userNameHwnd=win32gui.FindWindowEx(parentHwnd,currentAccountHwnd,None, None)  # 用户名框,基于【当前账套】控件句柄找到下一个即可83     time.sleep(0.1)84     win32gui.SendMessage(userNameHwnd, win32con.WM_SETTEXT, None,userName)85     time.sleep(0.1)86     win32gui.SendMessage(passwordHwnd, win32con.WM_SETTEXT, None,passWord)87 88 def sendReturn(sysLoginWnd):89     '''根据登陆界面句柄sysLoginWnd,发送回车键实现登录'''90     win32gui.PostMessage(sysLoginWnd, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)91     time.sleep(0.01)92     win32gui.PostMessage(sysLoginWnd, win32con.WM_KEYUP, win32con.VK_RETURN, 0)

 

欢迎扫码关注我的公众号 获取更多爬虫、数据分析的知识!

 

posted @ 2022-02-10 18:27 NewJune 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员