1、问题提出
在网页配置参数时,输入参数名称搜索,搜出来的同名参数结果有多个,分布在一个表格的不同行,表格是动态加载的,需要滚动鼠标才能把所出参数找出来。用selenium怎么实现这种参数修改?
2、网页元素的位置属性介绍
元素具有以下几何属性:
- offsetParent —— 是最接近的 CSS 定位的祖先,或者是 td,th,table,body。
- offsetLeft/offsetTop —— 是相对于 offsetParent 的左上角边缘的坐标。
- offsetWidth/offsetHeight —— 元素的“外部” width/height,边框(border)尺寸计算在内。
- clientLeft/clientTop —— 从元素左上角外角到左上角内角的距离。对于从左到右显示内容的操作系统来说,它们始终是左侧/顶部 border 的宽度。而对于从右到左显示内容的操作系统来说,垂直滚动条在左边,所以 clientLeft 也包括滚动条的宽度。
- clientWidth/clientHeight —— 内容的 width/height,包括 padding,但不包括滚动条(scrollbar)。
- scrollWidth/scrollHeight —— 内容的 width/height,就像 clientWidth/clientHeight 一样,但还包括元素的滚动出的不可见的部分。
- scrollLeft/scrollTop —— 从元素的左上角开始,滚动出元素的上半部分的 width/height。
- 除了 scrollLeft/scrollTop 外,所有属性都是只读的。如果我们修改 scrollLeft/scrollTop,浏览器会滚动对应的元素。
-
底部判断公式:
scrollBottom = scrollHeight - scrollTop - clientHeight;
如果没有滚动,或元素底部已经完全滚动完成,那么它应该返回 0
换句话说:(完全高度)减去(已滚出顶部的高度)减去(可见部分的高度)—— 得到的结果就是滚动出来的底部的部分。
-
滚动条的宽度计算:
为了获得滚动条的宽度,我们可以创建一个带有滚动条的元素,但是没有边框(border)和内边距(padding)。
然后,它的全宽度 offsetWidth 和内部内容宽度 clientWidth 之间的差值就是滚动条的宽度:
// 创建一个包含滚动条的 div
let div = document.createElement('div');
div.style.overflowY = 'scroll';
div.style.width = '50px';
div.style.height = '50px';
// 必须将其放入文档(document)中,否则其大小将为 0
document.body.append(div);
let scrollWidth = div.offsetWidth - div.clientWidth;
div.remove();
alert(scrollWidth);
3、实现代码:
# 定位到包含表格的元素
table = driver.find_element(By.XPATH, Table_Path) # 替换为实际的表格xpath
# 定义标志是否已经滚动到表格底部
scroll_end = False
# 模拟鼠标滚动并执行查找操作
while not scroll_end:
# 查找包含指定文本的单元格
cells = driver.find_elements(By.XPATH,
f"//td[.//span[contains(text(), '{filter_param}')]]")
print(f"cells len:{len(cells)}")
for cell in cells:
# 找到当前单元格元素所在行中的前一个单元格元素
left_cell = cell.find_element_by_xpath(f"./preceding-sibling::td[1]")
# 设置显式等待时间为10秒
wait = WebDriverWait(left_cell, 10)
# 读取左边第一个格子的内容
item = wait.until(EC.visibility_of_element_located((By.XPATH, "./div[2]")))
# 如果已经滚动到页面底部,退出循环
# 获取表格滚动后的高度
scroll_height = driver.execute_script("return arguments[0].scrollHeight", table)
client_height = driver.execute_script("return arguments[0].clientHeight", table)
scrollTop = driver.execute_script("return arguments[0].scrollTop", table)
print(f"client_height:{client_height}, scrollTop:{scrollTop}, scroll_height:{scroll_height}")
# 判断是否已经滚动到底部
if scroll_height - client_height - scrollTop < 20:
print("表格已经滚动到底部")
scroll_end = True
else:
print(f"表格尚未滚动到底部, scroll_current:{scrollTop + client_height}")
# 模拟按下 Page Down 键
table.send_keys(Keys.PAGE_DOWN)
time.sleep(2) # 等待加载