zoukankan      html  css  js  c++  java
  • 客户端的自动化

    前几天回归某款网游,发现重复任务太多,很想搞成自动操作,方便干其他事。

    原来用在工作中的UI自动化主要也是网页web,手机端的自动化,按理来说原理都一样,通过定位元素,对它们进行操作。

    于是我开始研究pywinauto,这是一个用python写的,对windows进行操作的库,加上spy++,通过线程号来找到对应程序。

    # 方式一:创建应用程序时可以,指定应用程序的合适的backend,start方法中指定启动的应用程序
    app = application.Application(backend='uia').start('notepad.exe') # start 参数可以是程序地址,通过cmd命令打开
    # 方式二:查看要打开的程序进程号,通过process指定进程号连接
    app = application.Application().connect(process=20456)
    # 输入操作
    edit.type_keys('柠檬')

    # 键盘操作
    from pywinauto.keyboard import send_keys
    from pywinauto import mouse

    send_keys('^a')
    send_keys('^c')
    send_keys('^v')
    send_keys('{VK_RETURN}') # 回车
    send_keys('^v')

    # 鼠标操作
    mouse.click(button='left', coords=(40, 40))
    # 指定位置 鼠标右击
    # mouse.click(button='right', coords=(100, 200))
    # 3.2 鼠标双击
    mouse.double_click(button='left', coords=(140, 40))
    # 4 按下鼠标:press
    # 将属性移动到(140,40)坐标处按下
    mouse.press(button='left', coords=(140, 40))
    # 5 释放鼠标:repleace
    # 将鼠标移动到(300,40)坐标处释放,
    mouse.release(button='left', coords=(300, 40))
    # 6、右键单击指定坐标
    mouse.right_click(coords=(400, 400))
    # 7、鼠标中键单击指定坐标(很少用的到)
    mouse.wheel_click(coords=(400, 400))
    # 8 滚动鼠标
    # coords:指定鼠标的坐标位置。
    # wheel_dist指定鼠标滚轮滑动的次数,正数往上,负数往下。
    mouse.scroll(coords=(1200, 300), wheel_dist=-3)
    放上网上别人操作navcat的代码

    import pywinauto
    from pywinauto import mouse
    from pywinauto.keyboard import send_keys
    import day5


    class NavicatTest:

    def __init__(self, path=None, precess=None):
    # 初始化一个应用程序对象
    if path:
    self.app = pywinauto.Application(backend="uia").start(path)
    else:
    self.app = pywinauto.Application(backend="uia").connect(process=precess)
    # 选择主窗口
    self.dlg = self.app["Navicat Premium"]

    # print('test1')
    # self.dlg.print_control_identifiers()

    # # 将控件列表写入文件
    # file_test1 = open('file_test1', mode='w')
    # file_test1.write(content)
    # file_test1.close()

    def new_connect(self, title, host, port, user, password):
    """
    新建连接
    """
    # 选择菜单栏
    menu = self.dlg["Menu"]

    # print('test2')
    # menu.print_control_identifiers()

    # 点击文件
    menu.child_window(title="文件", control_type="MenuItem").click_input()
    # 点击新建连接
    menu.item_by_path("文件->新建连接...").click_input()
    # 选择新建连接窗口
    new_dlg = self.app["新建连接"]
    # 连接名称输入框
    new_dlg["常规"].Edit5.type_keys(title)
    # ip输入框
    new_dlg["常规"].Edit1.type_keys(host)
    # 端口输入框
    new_dlg["常规"].Edit4.type_keys(port)
    # 用户名输入框
    new_dlg["常规"].Edit3.type_keys(user)
    # 密码输入框
    new_dlg["常规"].Edit2.type_keys(password)
    # 点击确定按钮
    new_dlg["确定"].click()

    def open_connect(self, title):
    """
    打开连接或者数据库
    :param title: 连接名或者数据库名
    :return:
    """
    # 获取控制坐标中心点,进行点击,打开连接
    db_name = self.dlg["TTreeView"].child_window(title=title, control_type="TreeItem")
    rect = db_name.rectangle().mid_point()
    print(rect.x, rect.y)
    mouse.double_click(coords=(rect.x, rect.y))

    def del_connect(self, title):
    """删除连接"""
    # 获取控件中心点位置
    db_name = self.dlg["TTreeView"].child_window(title=title, control_type="TreeItem")
    rect = db_name.rectangle().mid_point()
    # 鼠标在控件中心点,右击
    mouse.right_click(coords=(rect.x, rect.y))
    # 删除连接
    self.app["上下文"]["MenuItem5"].click_input()
    # 选择删除窗口
    self.app["确认删除"]["删除"].click()

    def close_coonnect(self, title):
    """
    关闭连接或者数据库
    :param title: 连接名或者数据库名
    :return:
    """
    # 获取控件中心点位置
    db_name = self.dlg["TTreeView"].child_window(title=title, control_type="TreeItem")
    rect = db_name.rectangle().mid_point()
    # 鼠标在控件中心点,右击
    mouse.right_click(coords=(rect.x, rect.y))
    # 删除连接
    self.app["上下文"]["MenuItem2"].click_input()

    def del_database(self, database):
    db_name = self.dlg["TTreeView"].child_window(title=database, control_type="TreeItem")
    rect = db_name.rectangle().mid_point()
    mouse.right_click(coords=(rect.x, rect.y))
    self.app["上下文"]["MenuItem4"].click_input()
    # 选择删除窗口
    self.app["确认删除"]["删除"].click()

    def new_database(self, title, database, charset="utf8 -- UTF-8 Unicode"):
    """新建数据库"""
    db_name = self.dlg["TTreeView"].child_window(title=title, control_type="TreeItem")
    rect = db_name.rectangle().mid_point()
    mouse.right_click(coords=(rect.x, rect.y))

    dlg = self.app["上下文"]
    # 点击新建连接
    dlg.MenuItem8.click_input()
    # 获取新建连接的窗口
    # self.app["新建数据库"].print_control_identifiers()
    # 数据数据库名
    self.app["新建数据库"]["常规"].Edit3.type_keys(database)
    self.app["新建数据库"]["常规"].Edit2.type_keys(charset)
    # 键盘回车键,点击确定
    send_keys("{VK_RETURN}")

    def new_find_dlg(self):
    """新建查询窗口"""
    find = self.dlg["TTreeView"].child_window(title="查询", control_type="TreeItem")
    # 获取查询的左边
    rect = find.rectangle().mid_point()
    # 鼠标右击
    mouse.right_click(coords=(rect.x, rect.y))
    # 选择出现的小窗口
    dlg = self.app["上下文"]
    # 点击新建连接
    dlg.MenuItem1.click_input()

    def find_sql(self, database, title, sql):
    """查询sql"""
    title = "无标题 @{} ({}) - 查询".format(database, title)
    find_dlg = self.app[title]
    find_dlg["TabControl"].print_control_identifiers()
    # 获取编辑框
    edit = find_dlg["TabControl"].Pane4
    # 获取编辑窗口控件位置
    rect = edit.rectangle().mid_point()
    mouse.click(coords=(rect.x, rect.y))
    sql = "^a{}".format(sql.replace(" ", "{VK_SPACE}")) + ";"
    send_keys(sql)
    # 使用运行快捷键
    send_keys("^r")


    if __name__ == '__main__':
    nav = NavicatTest(precess=5772)

    # 新建连接
    nav.new_connect(title="python666", host="localhost", port=3306, user="root", password="123456")

    # 打开连接
    nav.open_connect("win")

    # 关闭连接
    nav.close_coonnect("test")

    # 打开数据库
    nav.open_connect("test")

    # 新建查询窗口
    nav.new_find_dlg()

    # 查询数据
    sql = "SELECT * FROM students"
    nav.find_sql("test", "win", sql)

    # # 删除连接
    nav.del_connect("localhost_3306")

    原理确实是一样的。

    可问题来了,控件写满了几页,如何快速找到自己想要的控件呢?

    像浏览器找元素一般都有调试模式,可windows程序如何类似的去找呢,一行行往下找效率太低了,只有几个操作还行。

    wind.print_control_identifiers(),目前只有这个方法打印所有控件,呜呼...


  • 相关阅读:
    js获取url参数方法
    JQuery ajax 传递数组
    删除数组中的重复元素
    jquery load的使用
    css3 圆角
    一个项目最忌讳什么
    Lambda 表达式笔记
    KE ASP.NET取到kindeditor 编辑器数据
    ADO.NET
    .NET中Bind和Eval的区别
  • 原文地址:https://www.cnblogs.com/henry2019/p/14313916.html
Copyright © 2011-2022 走看看