Selenium XPath定位报错:结果为[object Text]应为元素如何解决
报错根因
Selenium 所有元素定位方法仅支持返回DOM元素对象,无法直接匹配XPath选出的文本节点,所以XPath末尾加/text()会直接抛出选择器无效的错误。如果去掉/text()直接获取betHeaderTitle节点的文本,会把该节点下所有子元素、文本节点的内容拼接后返回,自然没法直接拆分出两段独立内容。
实现方案
方案一:父元素遍历拆分法(稳定性最高,推荐)
你需要提取的两段文本分别属于betHeaderTitle下的两个位置:Home Win是内部span.market子元素的文本,PSV vs Ajax这类对阵信息是betHeaderTitle的直接文本节点。遍历的时候先拿子元素文本,再从父元素总文本里剔除子元素文本,就能得到独立的对阵内容。
注意Selenium 4.0+已经废弃了旧的find_elements_by_*系列方法,统一用By类定位,先导入依赖:
from selenium.webdriver.common.by import By
完整实现代码:
driver.get("https://footystats.org/predictions/home-wins") # 先定位所有投注卡片的父容器,避免多组数据索引错位 bet_cards = driver.find_elements(By.XPATH, "//div[@class='predictionsList']//div[@class='betWrapper ']") for card in bet_cards: # 提取预测类型:Home Win这类内容 prediction = card.find_element(By.XPATH, ".//span[@class='market']").text # 提取赔率内容 odds = card.find_element(By.XPATH, ".//div[@class='betHeaderMeta']").text # 提取标题总文本,剔除预测类型文本后剩余的就是对阵信息 title_node = card.find_element(By.XPATH, ".//div[@class='betHeaderTitle']") match_name = title_node.text.replace(prediction, "").strip() print(match_name, prediction, odds, sep="\t")
方案二:JS原生XPath提取法
如果不想做字符串替换,可以直接通过execute_script调用浏览器原生的XPath能力,直接提取文本节点内容,绕过Selenium的定位限制:
# 用JS直接提取betHeaderTitle下的直接文本节点 extract_text_js = """ const matchList = [] const textNodes = document.evaluate( "//div[@class='predictionsList']//div[@class='betWrapper ']//div[@class='betHeaderTitle']/text()", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null ) for(let i=0; i<textNodes.snapshotLength; i++){ const content = textNodes.snapshotItem(i).textContent.trim() if(content) matchList.push(content) } return matchList """ matches = driver.execute_script(extract_text_js) predictions = [e.text for e in driver.find_elements(By.XPATH, "//div[@class='predictionsList']//div[@class='betWrapper ']//span[@class='market']")] odds = [e.text for e in driver.find_elements(By.XPATH, "//div[@class='predictionsList']//div[@class='betWrapper ']//div[@class='betHeaderMeta']")] for idx in range(len(matches)): print(matches[idx], predictions[idx], odds[idx], sep="\t")
注意事项
- 优先选方案一,不会因为文本节点的空白字符、页面动态加载顺序问题出现索引错位
- 从父容器下查找子元素时,XPath开头要加
.,代表从当前元素节点往下查找,否则会从整个页面根节点匹配,导致内容错乱 - 如果用的是Selenium 3.x版本,也可以把
By写法换回旧的find_elements_by_xpath,但建议尽快升级版本兼容新API
内容的提问来源于stack exchange,提问作者Emre Oz
相关产品推荐
相关产品推荐

