selenium get element inside element 获取element的子element

本文详细解析了Selenium WebDriver中XPath的选择元素技巧,特别强调了全局(//)与局部(.//)选择的区别,帮助读者更精准地定位网页元素。
def click_all_clickable_elements(self, clicked_elements=None, left_clicked=None, top_clicked=None): if clicked_elements is None: clicked_elements = set() if left_clicked is None: left_clicked = set() if top_clicked is None: top_clicked = set() try: elements_locator = ( By.CSS_SELECTOR, 'button, a, input[type="button"], input[type="submit"], ' 'div[role="button"], div[onclick], [role="menuitem"], ' 'input[type="radio"],select,' '[role="option"], [data-testid*="button"], [class*="btn"], ' '[class*="clickable"]' ) original_url = self.driver.current_url original_window = self.driver.current_window_handle skip_values = ["提交", "导出", "下载"] # 优点击非菜单元素 while self.click_non_menu_elements(elements_locator, clicked_elements, skip_values, original_url, original_window): continue print("非菜单元素已全部点击,开始处理菜单逻辑") while True: try: left_menu = self.driver.find_element(By.ID, "subMenu") top_menu = self.driver.find_element(By.ID, "tabMenu") except Exception: print("无法找到菜单元素,结束流程") break # 获取 subMenu 中未点击的元素 sub_elements = left_menu.find_elements(By.XPATH, ".//button | .//a | .//input[@type='button']") valid_sub_elements = [e for e in sub_elements if self.element_actions.get_element_identifier(e) not in clicked_elements] if valid_sub_elements: # 点击一个 subMenu 元素 element = valid_sub_elements[0] element_id = self.element_actions.get_element_identifier(element) element.click() print(f"点击 subMenu 元素: {element_id}") clicked_elements.add(element_id) left_clicked.add(element_id) if self.pass_handler(self.driver.current_url): print("当前 URL 在跳过处理列表中,跳过递归点击") # self.handle_input_fields() # 点击后处理页面变化 self.handle_page_change(original_url, original_window) # 重新点击非菜单元素 while self.click_non_menu_elements(elements_locator, clicked_elements, skip_values, original_url, original_window): continue else: # subMenu 为空,尝试点击一个 tabMenu 元素 tab_elements = top_menu.find_elements(By.XPATH, ".//button | .//a | .//input[@type='button']") valid_tab_elements = [e for e in tab_elements if self.element_actions.get_element_identifier(e) not in top_clicked] if valid_tab_elements: element = valid_tab_elements[0] element_id = self.element_actions.get_element_identifier(element) element.click() print(f"点击 tabMenu 元素: {element_id}") top_clicked.add(element_id) if self.pass_handler(self.driver.current_url): print("当前 URL 在跳过处理列表中,跳过递归点击") # self.handle_input_fields() # 页面变化处理 self.handle_page_change(original_url, original_window) # 清空 left_clicked,允许重新点击 subMenu left_clicked.clear() # 再次点击非菜单元素 while self.click_non_menu_elements(elements_locator, clicked_elements, skip_values, original_url, original_window): continue else: print("tabMenu 和 subMenu 均无未点击元素,流程结束") break except Exception as e: print(f"处理可点击元素时出错: {str(e)}") # 点击非菜单元素 def click_non_menu_elements(self, locator, clicked_elements, skip_values, original_url, original_window): elements = self.driver.find_elements(*locator) count=len(elements) index = 0 for element in elements: index+=1 element_id_1 = self.element_actions.get_element_identifier(element) element_id=element_id_1.split('__')[-1] if element_id in clicked_elements: continue if self.is_menu_element(element_id): continue if not element.is_displayed() or not element.is_enabled(): continue value = element.get_attribute("value")#跳过提交/下载/导出 按钮 if value in skip_values: continue if element_id == "logout": continue # 跳过帮助按钮 href = element.get_attribute("href") text = element.text #跳过帮助按钮 if href and "solutions.brother.com" in href: continue if "Brother" in text and "Solutions" in text: continue # 点击元素 element.click() clicked_elements.add(element_id) if self.pass_handler(self.driver.current_url): print("当前 URL 在跳过处理列表中,跳过递归点击") print(f"点击非菜单元素{index}/{count}: {element_id}") # self.handle_input_fields() self.handle_page_change(original_url, original_window) return True # 表示点击了元素,继续循环 return False # 表示没有可点击的非菜单元素了 # 判断是否是菜单元素 def is_menu_element(self,element_id): try: left_menu = self.driver.find_element(By.ID, "subMenu") top_menu = self.driver.find_element(By.ID, "tabMenu") act_id=element_id.split("__")[-1] in_left = left_menu.find_element(By.XPATH, f".//descendant-or-self::*[@id='{act_id}']") in_top = top_menu.find_element(By.XPATH, f".//descendant-or-self::*[@id='{act_id}']") return in_left or in_top except: return False 上述代码写死菜单正确运行,下述代码有问题:有导航栏a(按钮a1 a2 a3 a4),b(b1 b2 b3),a1 a2 a3 a4可以正常点击,但是a1 a2 a3 下的b中的按钮不点击,点击切换后默认的界面的内容,a4下的b1 b2 b3及对应界面的元素都会被逐一点击,a4下的导航与非导航中的元素都可以被正确识别。 再a4下的都被点击后回退上一界面正常,但是回退完后会有点击导航栏元素失败(页面url发生变化,我重新获取了元素),两者点击的是同一个界面,我肯定页面加载没问题 def is_inside_navigation_bar(self, element): parent = element while True: try: parent = parent.find_element(By.XPATH, ‘…’) if parent.tag_name.lower() == ‘html’: return False tag_name = parent.tag_name.lower() class_name = parent.get_attribute(‘class’).lower() id_name = parent.get_attribute(‘id’).lower() if tag_name == ‘nav’ or any(kw in class_name for kw in [‘navbar’, ‘navigation’, ‘menu’]) or any(kw in id_name for kw in [‘nav’, ‘menu’]): return True except Exception as e: return False def click_all_clickable_elements(self, clicked_elements=None, depth=0, max_depth=20): if depth > max_depth: print("达到最大递归深度,停止点击") return if clicked_elements is None: clicked_elements = set() original_url = self.driver.current_url original_window = self.driver.current_window_handle elements = self.element_actions.get_all_clickable_elements() print(len(elements)) non_nav_elements = [] nav_elements = [] # 分类导航栏元素和非导航栏元素 for element in elements: try: element_id = self.element_actions.get_element_identifier(element) if element_id in clicked_elements: continue elements = self.element_actions.get_all_clickable_elements() if not element.is_displayed() or not element.is_enabled(): continue if self.is_inside_navigation_bar(element): nav_elements.append((element, element_id)) else: non_nav_elements.append((element, element_id)) except Exception as e: print(f"元素分类失败: {e}") continue # # 只提取 element_id # nav_ids = [element_id for element, element_id in nav_elements] # non_nav_ids = [element_id for element, element_id in non_nav_elements] # # # # 打印 ID 列表 # # print("导航栏元素 ID:") # # print("\n".join(nav_ids)) # # print(f"导航栏元素数量:{len(nav_ids)}\n") # # # # print("非导航栏元素 ID:") # # print("\n".join(non_nav_ids)) # # print(f"非导航栏元素数量:{len(non_nav_ids)}\n") # 优点击非导航栏元素 for element, element_id in non_nav_elements: try: if self.element_actions.is_sensitive_element(element): continue before_state = self.element_actions.get_page_state() self.element_actions.scroll_to_element(element) self.element_actions.highlight_element(element) self.element_actions.safe_click(element) clicked_elements.add(element_id) print(f"点击非导航栏元素: {element_id}") if self.pass_handler(self.driver.current_url): continue self.element_actions.handle_alert() self.element_actions.handle_new_windows(original_window) WebDriverWait(self.driver, 10).until( lambda d: self.element_actions.compare_states(before_state, self.element_actions.get_page_state()) ) if self.driver.current_url != original_url: WebDriverWait(self.driver, 10).until( EC.presence_of_element_located((By.TAG_NAME, 'body')) ) self.click_all_clickable_elements(clicked_elements, depth=depth + 1) self.driver.back() non_nav_elements = self.element_actions.get_all_clickable_elements() # 重新获取元素 WebDriverWait(self.driver, 10).until(EC.url_to_be(original_url)) except Exception as e: print(f"点击非导航栏元素失败: {e}") continue # 检查是否非导航栏元素已全部点击 if len(clicked_elements) >= len(non_nav_elements): # 开始点击导航栏元素 for element, element_id in nav_elements: if element_id in clicked_elements: continue try: before_state = self.element_actions.get_page_state() self.element_actions.scroll_to_element(element) self.element_actions.highlight_element(element) self.element_actions.safe_click(element) clicked_elements.add(element_id) print(f"点击导航栏元素: {element_id}") nav_elements = self.element_actions.get_all_clickable_elements() if self.pass_handler(self.driver.current_url): continue self.element_actions.handle_alert() self.element_actions.handle_new_windows(original_window) WebDriverWait(self.driver, 10).until( lambda d: self.element_actions.compare_states(before_state, self.element_actions.get_page_state()) ) if self.driver.current_url != original_url: WebDriverWait(self.driver, 10).until( EC.presence_of_element_located((By.TAG_NAME, 'body')) ) nav_elements = self.element_actions.get_all_clickable_elements() self.click_all_clickable_elements(clicked_elements, depth=depth + 1) self.driver.back() WebDriverWait(self.driver, 10).until(EC.url_to_be(original_url)) except Exception as e: print(f"点击导航栏元素失败: {e}") continue print("当前页面所有元素已点击完毕")
08-26
这是代码 def is_inside_navigation_bar(self, element): parent = element while True: try: parent = parent.find_element(By.XPATH, '..') if parent.tag_name.lower() == 'html': return False tag_name = parent.tag_name.lower() class_name = parent.get_attribute('class').lower() id_name = parent.get_attribute('id').lower() if tag_name == 'nav' or \ any(kw in class_name for kw in ['navbar', 'navigation', 'menu']) or \ any(kw in id_name for kw in ['nav', 'menu']): return True except Exception as e: return False def click_all_clickable_elements(self, clicked_elements=None, depth=0, max_depth=20): if depth > max_depth: print("达到最大递归深度,停止点击") return if clicked_elements is None: clicked_elements = set() original_url = self.driver.current_url original_window = self.driver.current_window_handle elements = self.element_actions.get_all_clickable_elements() non_nav_elements = [] nav_elements = [] # 分类导航栏元素和非导航栏元素 for element in elements: try: element_id = self.element_actions.get_element_identifier(element) if element_id in clicked_elements: continue elements = self.element_actions.get_all_clickable_elements() if not element.is_displayed() or not element.is_enabled(): continue if self.is_inside_navigation_bar(element): nav_elements.append((element, element_id)) else: non_nav_elements.append((element, element_id)) except Exception as e: print(f"元素分类失败: {e}") continue # 优点击非导航栏元素 for element, element_id in non_nav_elements: try: if self.element_actions.is_sensitive_element(element): continue before_state = self.element_actions.get_page_state() self.element_actions.scroll_to_element(element) self.element_actions.highlight_element(element) self.element_actions.safe_click(element) clicked_elements.add(element_id) print(f"点击非导航栏元素: {element_id}") if self.pass_handler(self.driver.current_url): continue self.element_actions.handle_alert() self.element_actions.handle_new_windows(original_window) WebDriverWait(self.driver, 10).until( lambda d: self.element_actions.compare_states(before_state, self.element_actions.get_page_state()) ) if self.driver.current_url != original_url: WebDriverWait(self.driver, 10).until( EC.presence_of_element_located((By.TAG_NAME, 'body')) ) self.click_all_clickable_elements(clicked_elements, depth=depth + 1) self.driver.back() non_nav_elements = self.element_actions.get_all_clickable_elements() # 重新获取元素 WebDriverWait(self.driver, 10).until(EC.url_to_be(original_url)) except Exception as e: print(f"点击非导航栏元素失败: {e}") continue # 检查是否非导航栏元素已全部点击 if len(clicked_elements) >= len(non_nav_elements): # 开始点击导航栏元素 for element, element_id in nav_elements: if element_id in clicked_elements: continue try: before_state = self.element_actions.get_page_state() self.element_actions.scroll_to_element(element) self.element_actions.highlight_element(element) self.element_actions.safe_click(element) clicked_elements.add(element_id) print(f"点击导航栏元素: {element_id}") if self.pass_handler(self.driver.current_url): continue self.element_actions.handle_alert() self.element_actions.handle_new_windows(original_window) WebDriverWait(self.driver, 10).until( lambda d: self.element_actions.compare_states(before_state, self.element_actions.get_page_state()) ) if self.driver.current_url != original_url: WebDriverWait(self.driver, 10).until( EC.presence_of_element_located((By.TAG_NAME, 'body')) ) nav_elements = self.element_actions.get_all_clickable_elements() self.click_all_clickable_elements(clicked_elements, depth=depth + 1) self.driver.back() WebDriverWait(self.driver, 10).until(EC.url_to_be(original_url)) except Exception as e: print(f"点击导航栏元素失败: {e}") continue print("当前页面所有元素已点击完毕"),我确定a1 a2 a3 a4加载方式、结构相同,
08-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值