python Selenium 如何在 XPath 1.0 中处理动态 XPath



我必须选择一个XPath是动态的字段。在不同的会话中,这些是 XPath 的示例:

htmlb_335660_htmlb_115101_1
htmlb_323002_htmlb_110159_1
htmlb_331156_htmlb_111919_1
htmlb_335204_htmlb_114985_1
htmlb_324009_htmlb_110479_1
htmlb_331374_htmlb_111629_1
htmlb_331140_htmlb_112463_1
htmlb_324978_htmlb_110752_1
htmlb_324725_htmlb_110669_1
htmlb_336067_htmlb_115248_1
htmlb_324854_htmlb_110713_1
htmlb_334552_htmlb_112898_1
htmlb_415158_htmlb_142073_1

这是 html 代码:

这是我唯一可以成功用于检测字段的 3 个代码片段:

ids = browser.find_elements_by_xpath("//*[contains(text(), 'htmlb_') and contains(text(), 'htmlb_') and contains(text(), '_1')]")
ids = browser.find_elements_by_xpath("//*[starts-with(text(), 'htmlb_')]")
ids = browser.find_elements_by_xpath("//*[substring(@id, string-length(@id) - 1) = '_1']")
for ii in ids:
print(">",ii)

当我尝试获取属性("id"、"名称"、"标题"、"href"等(时,所有打印都给出"找不到属性"或"无"。我想以失败开头运行良好,以失败结束,因为结尾是 XPath 2.0,大多数浏览器都不支持 Selenium 它。

所以我"盲目"检测 3 个字段,但除了我按上述("ii"(打印对象时,我看不到字段的更多详细信息:然后我得到:

> <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="a0779322-035d-41af-bb32-9c35973d3317", element="998d9583-79c8-4192-a078-c2d8719bbd9e")>
> <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="a0779322-035d-41af-bb32-9c35973d3317", element="25fa3805-7794-4760-b355-1ed408472e1d")>
> <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="a0779322-035d-41af-bb32-9c35973d3317", element="52f1ea41-3a27-4a62-8153-b38e31c1beaa")>

所有这些语句都失败了:

ids = browser. find_elements_by_id("id^='htmlb'"(

ids = browser.find_elements_by_xpath("//*[ends-with(text((, 'htmlb_'(]"(

id = browser.find_elements_by_id('htmlb_'+ '\d{6}' + 'htmlb' + '\d{6}' + '_1'( <-- 这个会解决我的问题!!我为什么不工作?

抱歉,HTML 代码在上面丢失了:

<input type="text" class="urEdf2TxtEnbl" usedclasses="urEdf2TxtInv urEdf2TxtWarn urEdf2TxtRo urEdf2TxtRoInv urEdf2TxtRoWarn urEdf2TxtDsbl urEdf2TxtHlp" autocomplete="off" id="htmlb_425962_htmlb_146807_1" ct="I" name="htmlb_425962_htmlb_146807_1" st="" tp="STRING" f4always="false" tabindex="0" ti="0" title="Datoformat skal være dd-mm-åååå" value="04-07-2020" onchange="sapUrMapi_InputField_change('htmlb_425962_htmlb_146807_1',event);" onblur="sapUrMapi_InputField_Blur('htmlb_425962_htmlb_146807_1',event);" onkeydown="sapUrMapi_InputField_keydown('htmlb_425962_htmlb_146807_1',event);" onkeyup="sapUrMapi_InputField_KeyUp('htmlb_425962_htmlb_146807_1',event);" onfocus="sapUrMapi_InputField_focus('htmlb_425962_htmlb_146807_1',event);" onselectstart="sapUrMapi_InputField_onselectstart('htmlb_425962_htmlb_146807_1',event);" style="width:80px;" oldvalue="04-07-2020">

好的,我找到了一个返回对象的解决方案:

browser.find_elements_by_xpath("//*[substring(@id, 1, 6) = 'htmlb_' and substring(@id, string-length(@id) - 1) = '_1']")

但是我有一个框架问题,还没有找到合适的对象。

一些评论。两个 XPath 表达式不适用于示例数据。第一:

//*[contains(text(), 'htmlb_') and contains(text(), 'htmlb_') and contains(text(), '_1')]

您必须指定评估id属性,而不是元素。另请注意两个不同的htmlb(下划线的位置(。

//input[contains(@id, 'htmlb_') and contains(@id, '_htmlb') and contains(@id, '_1')]

第二:

//*[starts-with(text(), 'htmlb_')]

您必须指定评估id属性,而不是元素:

//input[starts-with(@id, 'htmlb_')]

第三个和第四个XPath完全没问题。所以总结一下,你可以使用以下XPath(3个谓词(:

//input[starts-with(@id, 'htmlb_')][contains(@id, '_htmlb')][substring(@id, string-length(@id) - 1) = '_1']

或者将这个与翻译功能一起使用:

//input[translate(@id,"0123456789","nnnnnnnnnn")="htmlb_nnnnnn_htmlb_nnnnnn_n"]

要使用的通用代码(框架支持(单击元素:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
frame = driver.find_element_by_xpath("xpath_to_the_frame")
driver.switch_to_frame(frame)
WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.XPATH, "one_of_the_preceding_xpath"))).click()

旁注 : 正如你所说,Selenium 不支持 XPath 2.0,所以你不能使用function。 AFAIK 您不能将正则表达式与find_elements_by_id方法一起使用。

最新更新