コード例 #1
0
class GetUI(object):
    def __init__(self, adb_ext):
        self.__adb_ext = adb_ext
        self.xml = None
        self.ocr = None
        self.init_ocr()
        self.shape = None
        self.custom_xml_path = None  # 使用自定义的xml文件
        self.is_py2 = sys.version_info < (3, 0)

    def init_ocr(self, app_id=None, secret_id=None, secret_key=None):
        if app_id is None and secret_id is None and secret_key is None:
            # 以下为测试账号,任何人可用,但是随时都会不可用,建议自行去腾讯优图申请专属账号
            app_id = '10126986'
            secret_id = 'AKIDT1Ws34B98MgtvmqRIC4oQr7CBzhEPvCL'
            secret_key = 'AAyb3KQL5d1DE4jIMF2f6PYWJvLaeXEk'
        self.ocr = Ocr(app_id, secret_id, secret_key)

    def init_shape(self):
        from adbui.shape import Shape
        self.shape = Shape()

    def get_ui_by_attr(self, is_contains=False, is_update=True, **kwargs):
        uis = self.get_uis_by_attr(is_contains=is_contains,
                                   is_update=is_update,
                                   **kwargs)
        return uis[0] if uis else None

    def get_uis_by_attr(self, is_contains=False, is_update=True, **kwargs):
        """
        通过节点的属性获取节点
        :param is_contains: 是否使用模糊查找
        :param is_update:
        :param kwargs:
        :return: 
        """
        for key in kwargs:
            if key in short_keys:
                kwargs[short_keys[key]] = kwargs.pop(key)
        if is_contains:
            s = list(
                map(lambda x: "contains(@{}, '{}')".format(x, kwargs[x]),
                    kwargs))
            xpath = './/*[{}]'.format(' and '.join(s))
        else:
            s = list(
                map(lambda key: "[@{}='{}']".format(key, kwargs[key]), kwargs))
            xpath = './/*{}'.format(''.join(s))
        uis = self.get_uis_by_xpath(xpath, is_update=is_update)
        return uis

    def get_ui_by_xpath(self, xpath, is_update=True):
        uis = self.get_uis_by_xpath(xpath, is_update)
        return uis[0] if uis else None

    def get_uis_by_xpath(self, xpath, is_update=True):
        """
        通过xpath查找节点
        :param xpath: 
        :param is_update: 
        :return: 
        """
        if is_update:
            self.__adb_ext.dump()  # 获取xml文件
            self.__init_xml()
        xpath = xpath.decode('utf-8') if sys.version_info[0] < 3 else xpath
        elements = self.xml.xpath(xpath)
        uis = []
        for element in elements:
            uis.append(self.get_ui_by_element(element))
        return uis

    def get_ui_by_element(self, element):
        bounds = element.get('bounds')
        x1, y1, x2, y2 = re.compile(r"-?\d+").findall(bounds)
        ui = UI(self.__adb_ext, x1, y1, x2, y2)
        ui.element = element
        ui.text = element.get('text')
        return ui

    def get_ui_by_ocr(self, text, min_hit=None, is_update=True):
        uis = self.get_uis_by_ocr(text, min_hit, is_update)
        return uis[0] if uis else None

    def get_uis_by_ocr(self, text, min_hit=None, is_update=True):
        """
        通过ocr识别获取节点
        :param text: 查找的文本
        :param min_hit: 设置查找文本的最小匹配数量
        :param is_update: 是否重新获取截图
        :return: 
        """
        if self.ocr is None:
            raise NameError(
                'ocr 功能没有初始化.请到 adbui 页面查看如何使用。\nhttps://github.com/hao1032/adbui'
            )
        if is_update:
            self.__adb_ext.screenshot()  # 获取截图
        image_jpg = self.__get_image_jpg()
        ocr_result = self.ocr.get_result_image(image_jpg)
        if 'httpcode' in ocr_result and ocr_result['httpcode'] == 510:
            raise NameError('OCR 服务调用频率限制或者连接数限制,请使用自己申请的账号。')
        text = text.decode('utf-8') if self.is_py2 and isinstance(
            text, str) else text
        text_list = list(text)
        min_hit = min_hit if min_hit else len(
            text_list)  # 如果min hit没有指定,使用min text的长度
        uis = []
        for item in ocr_result['items']:
            same_count = 0
            item_string = item['itemstring']
            item_string = item_string.decode(
                'utf-8') if self.is_py2 and isinstance(item_string,
                                                       str) else item_string
            item_string_list = list(item_string)

            # 计算 text_list 和 item_string_list 中相同元素的数量
            for char in text_list:
                if char in item_string_list:
                    item_string_list.pop(item_string_list.index(char))
                    same_count += 1

            if same_count >= min_hit:
                item_coord = item['itemcoord']
                ui = UI(self.__adb_ext, item_coord['x'], item_coord['y'],
                        item_coord['x'] + item_coord['width'],
                        item_coord['y'] + item_coord['height'])
                ui.text = item_string
                uis.append(ui)
        return uis

    def get_text_by_ocr(self, ui=None, rect=None, is_update=False):
        pass

    def get_ui_by_shape(self, width_range, height_range, box=None):
        uis = self.get_uis_by_shape(width_range, height_range, box)
        return uis[0] if uis else None

    def get_uis_by_shape(self, width_range, height_range, box=None):
        self.__adb_ext.screenshot()  # 获取截图
        jpg_img = self.__get_image_jpg()
        if box:
            jpg_img = jpg_img.crop(box)
        rectangles = self.shape.get_rectangle(jpg_img, width_range,
                                              height_range)
        uis = []
        for x1, y1, x2, y2, width, height in rectangles:
            ui = UI(self.__adb_ext, x1, y1, x2, y2)
            uis.append(ui)
        return uis

    def __get_image_jpg(self):
        img_path = '{}.png'.format(self.__adb_ext.get_pc_temp_name())
        return Image.open(img_path).convert('RGB')

    def __init_xml(self):
        if self.custom_xml_path is None:
            xml_path = '{}.xml'.format(self.__adb_ext.get_pc_temp_name())
        else:
            xml_path = self.custom_xml_path
        self.xml = etree.parse(xml_path)
        for element in self.xml.findall('.//node'):
            element.tag = element.get('class').split('.')[-1].replace(
                '$', '')  # 将每个node的name替换为class值,和uiautomator里显示的一致

        try:
            self.original_xml = etree.tostring(
                self.xml, pretty_print=True,
                encoding='utf-8').decode()  # 原始 xml
            self.replace_xml = etree.tostring(
                self.xml, pretty_print=True,
                encoding='utf-8').decode()  # 替换后的 xml
        except:
            self.replace_xml = etree.tostring(
                self.xml, pretty_print=True).decode()  # 替换后的 xml
            self.original_xml = etree.tostring(
                self.xml, pretty_print=True).decode()  # 原始 xml
コード例 #2
0
 def init_shape(self):
     from adbui.shape import Shape
     self.shape = Shape()
コード例 #3
0
class GetUI(object):
    def __init__(self, adb_ext):
        self.__adb_ext = adb_ext
        self.xml = None
        self.ocr = None
        self.shape = None

    def init_ocr(self, app_id=None, secret_id=None, secret_key=None):
        self.ocr = Ocr(app_id, secret_id, secret_key)

    def init_shape(self):
        from adbui.shape import Shape
        self.shape = Shape()

    def get_ui_by_attr(self, is_contains=False, is_update=True, **kwargs):
        uis = self.get_uis_by_attr(is_contains=is_contains,
                                   is_update=is_update,
                                   **kwargs)
        return uis[0] if uis else None

    def get_uis_by_attr(self, is_contains=False, is_update=True, **kwargs):
        """
        通过节点的属性获取节点
        :param is_contains: 是否使用模糊查找
        :param is_update:
        :param kwargs:
        :return: 
        """
        for key in kwargs:
            if key in short_keys:
                kwargs[short_keys[key]] = kwargs.pop(key)
        if is_contains:
            s = list(
                map(lambda x: "contains(@{}, '{}')".format(x, kwargs[x]),
                    kwargs))
            xpath = './/*[{}]'.format(' and '.join(s))
        else:
            s = list(
                map(lambda key: "[@{}='{}']".format(key, kwargs[key]), kwargs))
            xpath = './/*{}'.format(''.join(s))
        uis = self.get_uis_by_xpath(xpath, is_update=is_update)
        return uis

    def get_ui_by_xpath(self, xpath, is_update=True):
        uis = self.get_uis_by_xpath(xpath, is_update)
        return uis[0] if uis else None

    def get_uis_by_xpath(self, xpath, is_update=True):
        """
        通过xpath查找节点
        :param xpath: 
        :param is_update: 
        :return: 
        """
        if is_update:
            self.__adb_ext.dump()  # 获取xml文件
            self.__init_xml()
        xpath = xpath.decode('utf-8') if sys.version_info[0] < 3 else xpath
        elements = self.xml.xpath(xpath)
        uis = []
        for element in elements:
            uis.append(self.get_ui_by_element(element))
        return uis

    def get_ui_by_element(self, element):
        bounds = element.get('bounds')
        x1, y1, x2, y2 = re.compile(r"-?\d+").findall(bounds)
        ui = UI(self.__adb_ext, x1, y1, x2, y2,
                int(x2) - int(x1),
                int(y2) - int(y1))
        ui.element = element
        return ui

    def get_ui_by_ocr(self, text, min_hit=None, is_update=True):
        uis = self.get_uis_by_ocr(text, min_hit, is_update)
        return uis[0] if uis else None

    def get_uis_by_ocr(self, text, min_hit=None, is_update=True):
        """
        通过ocr识别获取节点
        :param text: 查找的文本
        :param min_hit: 设置查找文本的最小匹配数量
        :param is_update: 是否重新获取截图
        :return: 
        """
        if self.ocr is None:
            raise NameError(
                'ocr is not init.how init find at https://github.com/hao1032/adbui'
            )
        if is_update:
            self.__adb_ext.screenshot()  # 获取截图
        image_jpg = self.__get_image_jpg()
        ocr_result = self.ocr.get_result_image(image_jpg)
        text_list = list(text)
        min_hit = min_hit if min_hit else len(
            text_list)  # 如果min hit没有指定,使用min text的长度
        uis = []
        for item in ocr_result['items']:
            same_count = 0
            item_string = item['itemstring']
            item_string_list = list(item_string)

            # 计算 text_list 和 item_string_list 中相同元素的数量
            for char in text_list:
                if char in item_string_list:
                    item_string_list.pop(item_string_list.index(char))
                    same_count += 1

            if same_count >= min_hit:
                item_coord = item['itemcoord']
                ui = UI(self.__adb_ext, item_coord['x'], item_coord['y'],
                        item_coord['x'] + item_coord['width'],
                        item_coord['y'] + item_coord['height'],
                        item_coord['width'], item_coord['height'])
                ui.text = item_string
                uis.append(ui)
        return uis

    def get_text_by_ocr(self, ui=None, rect=None, is_update=False):
        pass

    def get_ui_by_shape(self, width_range, height_range, box=None):
        uis = self.get_uis_by_shape(width_range, height_range, box)
        return uis[0] if uis else None

    def get_uis_by_shape(self, width_range, height_range, box=None):
        self.__adb_ext.screenshot()  # 获取截图
        jpg_img = self.__get_image_jpg()
        if box:
            jpg_img = jpg_img.crop(box)
        rectangles = self.shape.get_rectangle(jpg_img, width_range,
                                              height_range)
        uis = []
        for x1, y1, x2, y2, width, height in rectangles:
            ui = UI(self.__adb_ext, x1, y1, x2, y2, width, height)
            uis.append(ui)
        return uis

    def __get_image_jpg(self):
        img_path = '{}.png'.format(self.__adb_ext.get_pc_temp_name())
        return Image.open(img_path).convert('RGB')

    def __init_xml(self):
        xml_path = '{}.xml'.format(self.__adb_ext.get_pc_temp_name())
        self.xml = etree.parse(xml_path)

        for element in self.xml.findall('.//node'):
            element.tag = element.get('class').split('.')[
                -1]  # 将每个node的name替换为class值,和uiautomator里显示的一致