。。。。
# 使用提醒:
# 1. xbot包提供软件自动化、数据表格、Excel、日志、AI等功能
# 2. package包提供访问当前应用数据的功能,如获取元素、访问全局变量、获取资源文件等功能
# 3. 当此模块作为流程独立运行时执行main函数
# 4. 可视化流程中可以通过"调用模块"的指令使用此模块
import xbot
from xbot import print, sleep
from . import package
from .package import _selector_store, selector, resources
from .package import variables as glv
from xbot.selector import SelectorStore, ImageSelectorStore
from xbot.primitives import VariableDict, ResourceReader, _sdmodules
import xml.etree.ElementTree as ET
import os, re
import time
def generate_selector(uids, last_name=None, last_uid=None):
value = {"name":"iframe", "type":"simple"}
path = []
for uid in uids:
path.append({"name":"iframe","type":"web","attributes": [{'name': 'diy-uid', 'value': f"{uid}", 'required': True, 'operator': 'Equal'}]})
if last_name:
path.append({"name":last_name,"type":"web","attributes": [{'name': 'diy-uid', 'value': f"{last_uid}", 'required': last_uid is not None, 'operator': 'Equal'}]})
value["path"] = path
return xbot.selector.Selector(value)
def get_uid(uids=[]):
uid = str(int(time.time() * 1000))
if uid in uids:
uid = str(int(time.time() * 1000))
return uid
class IframePage:
def __init__(self, web_page, iframe=None, uids=[], iframe_page_list=[]):
self.web_page = web_page
self.iframe = web_page if iframe is None else iframe
self.iframe_page_list = iframe_page_list
self.uids = uids
def read_ele(self, uids, last_name, last_uid=None, single=True):
_selector = generate_selector(uids, last_name=last_name, last_uid=last_uid)
if single:
return self.web_page.find(_selector, timeout=0)
return self.web_page.find_all(_selector, timeout=0)
def to_iframe(self, xpath, find_descendant_iframe=False):
"""
通过xpath切换到iframe
"""
if find_descendant_iframe:
total = 0
list_iframe_page = self.find_all_iframe()
new_iframe_page = None
for iframe_page in list_iframe_page:
try:
new_iframe_page = iframe_page.to_iframe(xpath)
if total != 0:
raise Exception("找到多个iframe元素,无法唯一定位")
total += 1
except Exception as e:
msg = e.args[0]
if msg == "找到多个元素,无法唯一定位" or msg == "找到多个iframe元素,无法唯一定位":
raise
if new_iframe_page is None:
raise Exception("未找到元素")
return new_iframe_page
iframe_ele = self.find_ele(xpath, True)
uids = self.uids.copy()
return IframePage(self.web_page, iframe_ele, uids)
# @record_time
def find_ele(self, xpath, is_iframe=False):
"""
获取元素对象
"""
uid = None
if self.iframe != self.web_page:
html_ele = self.read_ele(self.uids, "html")
code = """
function (element, xpath) {
$x = (xpath) => {
try {
let xpathResult = document.evaluate(xpath, element, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
let nodes = []
let node = null
while (node = xpathResult.iterateNext()) {
nodes.push(node)
}
return nodes
} catch (error) {
return []
}
}
let eles = $x(xpath)
if (eles.length > 1) {
return ["", "", "找到多个元素,无法唯一定位"]
}
if (eles.length == 0) {
return ["", "", "未找到元素"]
}
let ele = eles[0]
let uid = ele.getAttribute("diy-uid")
if (uid == null || uid == "") {
uid = new Date().getTime().toString()
ele.setAttribute("diy-uid", uid)
}
return [uid, ele.tagName, "成功"]
}
"""
uid, tag_name, msg = html_ele.execute_javascript(code, xpath)
if msg != "成功":
raise Exception(msg)
ele = self.read_ele(self.uids, tag_name, uid)
else:
ele = self.web_page.find_by_xpath(xpath, timeout=1)
uid = get_uid()
ele.set_attribute("diy-uid", uid)
if is_iframe:
self.uids.append(uid)
return ele
def find_ele2(self, xpath):
"""
获取元素对象-跨多层iframe
"""
start_time = time.time()
iframe_page_list = self.find_all_iframe()
end_time = time.time()
eles = []
start_time = time.time()
for iframe_page in iframe_page_list:
try:
ele = iframe_page.find_ele(xpath)
eles.append(ele)
except:
pass
end_time = time.time()
if len(eles) == 1:
return eles[0]
if len(eles) == 0:
raise Exception("未找到元素")
raise Exception("找到多个元素,无法唯一定位")
# @record_time
def find_all_iframe(self):
"""基于当前iframe 查找所有后代 iframe (包含自身)"""
uids = self.uids.copy()
if len(self.uids) == 0:
iframe_eles = self.web_page.find_all_by_xpath("//iframe", timeout=0.1)
else:
iframe_eles = self.read_ele(uids,"iframe",None,False)
iframe_page_list = [self]
self._find_all_iframe(iframe_eles, uids, iframe_page_list)
return iframe_page_list
def _find_all_iframe(self, iframe_eles, uids, iframe_page_list):
if len(iframe_eles) == 0:
return
for iframe_ele in iframe_eles:
uid = iframe_ele.get_attribute("diy-uid")
print("id", iframe_ele.get_attribute("id"))
if uid is None or uid == "":
uid = get_uid()
iframe_ele.set_attribute("diy-uid", uid)
uids.append(uid)
iframe_page = IframePage(self.web_page, iframe_ele, uids.copy())
iframe_page_list.append(iframe_page)
iframe_eles = self.read_ele(uids,"iframe",None,False)
self._find_all_iframe(iframe_eles, uids, iframe_page_list)
uids.pop(-1)
def find_all_ele(self, xpath, find_descendant_iframe=False):
"""
获取相似元素列表
"""
eles = []
code = """
function (element, xpath) {
function $x(xpath) {
let xpathResult = document.evaluate(xpath, element, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
let nodes = []
let node = null
while (node = xpathResult.iterateNext()) {
nodes.push(node)
}
return nodes
}
function get_uid(uids) {
let uid = new Date().getTime().toString()
while (uids.includes(uid)) {
uid += "0"
}
return uid
}
let uids = []
ele_info = []
eles = $x(xpath)
for (let i = 0; i < eles.length; i++) {
let ele = eles[i]
let uid = ele.getAttribute("diy-uid")
if (uid == null || uid == "") {
uid = get_uid(uids)
ele.setAttribute("diy-uid", uid)
}
uids.push(uid)
ele_info.push([uid, ele.tagName])
}
return ele_info
}
"""
if find_descendant_iframe:
total = 0
eles = []
list_iframe_page = self.find_all_iframe()
for iframe_page in list_iframe_page:
temp_eles = iframe_page.find_all_ele(xpath)
if len(temp_eles) != 0:
total += 1
eles = temp_eles
if total > 1:
raise Exception("在多个iframe中找到相似元素,无法唯一定位")
return eles
if self.iframe != self.web_page:
uids = self.uids.copy()
html_ele = self.read_ele(uids,"html")
ele_info = html_ele.execute_javascript(code, xpath)
for uid, tag_name in ele_info:
ele = self.read_ele(uids, tag_name, uid)
eles.append(ele)
else:
eles = self.web_page.find_all_by_xpath(xpath, timeout=3)
return eles
def main(args):
web_page = xbot.web.get("*E*", mode='edge', use_wildcard=True)
iframe_page = IframePage(web_page)
# //*[@id="s_filter_frame"]
# iframe_page = iframe_page.to_iframe('//*[@id="form1"]/div[7]/div[2]/table/tbody/tr/td[1]/iframe', find_descendant_iframe=True)
# iframe_page.find_ele('//*[@id="as_id"]')
# ###### 示例一
# # 初始化iframe处理器
# iframe_page = IframePage(web_page)
# # 切换iframe
# iframe_page = iframe_page.to_iframe('//*[@id="QQMailSdkTool_login_loginBox_qq"]/iframe')
# iframe_page = iframe_page.to_iframe('//*[@id="ptlogin_iframe"]')
# # 查找元素
# name_ele = iframe_page.find_ele('//*[@id="u"]')
# name_ele.input("23124325")
# ###### 示例二
# # 初始化iframe处理器
# iframe_page = IframePage(web_page)
# # 跨层级切换iframe
# iframe_page = iframe_page.to_iframe('//*[@id="ptlogin_iframe"]', find_descendant_iframe=True)
# # 查找元素
# name_ele = iframe_page.find_ele('//*[@id="u"]')
# ###### 示例三
# # 初始化iframe处理器
# iframe_page = IframePage(web_page)
# # 跨层级查找元素
name_ele = iframe_page.find_ele2('//*[@id="o_id"]').click()
pass