Python Selenium通过XPath定位ul元素遍历li获取属性方法
Python Selenium定位指定ul下li并提取title属性解决方案
问题相关参考材料
定位失败常见原因排查
定位返回空90%以上是以下几个问题,按顺序排查即可:
- 目标元素嵌套在
iframe标签内:Selenium默认只能定位当前顶层页面的元素,iframe相当于页面里嵌了另一个独立网页,必须先切换到对应iframe才能定位内部元素,切换代码:
操作完iframe内元素如果要回到外层页面,执行# 替换括号里的定位逻辑为你页面中iframe的定位方式,比如id、class都可以 driver.switch_to.frame(driver.find_element(By.ID, "iframe的id值"))driver.switch_to.default_content()即可。 - 元素是动态渲染/懒加载的:页面刚打开时元素还没加载完成,直接定位就会返回空,不要用
time.sleep()硬等,用显式等待自动判断元素加载状态,效率更高也更稳定。 - 写的定位路径是绝对路径:类似
/html/body/div[2]/div[3]/ul这种从根节点开始写的绝对路径,页面结构稍微变动就会失效,优先用元素本身的稳定属性(id、固定class、自定义属性)做锚点定位。
可直接复用的实现代码
先确保你已经安装了4.0以上版本的Selenium,直接用下面的逻辑即可:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.action_chains import ActionChains # 初始化浏览器,启动后最大化窗口避免响应式布局导致元素被隐藏 driver = webdriver.Chrome() driver.maximize_window() driver.get("替换为你要爬取的目标页面地址") # 初始化显式等待,最长等待15秒,每0.5秒检查一次元素是否存在 wait = WebDriverWait(driver, 15) # 定位目标ul,根据你页面的实际属性选一种定位方式即可 # 方式1:ul有id属性(最稳定,优先用) # target_ul = wait.until(EC.presence_of_element_located((By.ID, "替换为ul的id属性值"))) # 方式2:ul有固定class属性 target_ul = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "ul.替换为ul的class属性值"))) # 方式3:ul本身没有稳定属性,找上层有稳定属性的父节点往下找 # target_ul = wait.until(EC.presence_of_element_located((By.XPATH, "//div[@class='父节点稳定class值']//ul"))) # 提取ul下所有li标签 li_elements = target_ul.find_elements(By.TAG_NAME, "li") result = [] for li in li_elements: # 滚动到当前li位置,触发懒加载渲染 driver.execute_script("arguments[0].scrollIntoViewIfNeeded();", li) # 如果li的title属性是鼠标悬浮才加载,就放开下面这行注释 # ActionChains(driver).move_to_element(li).perform() # 提取title属性 title_val = li.get_attribute("title") if title_val: result.append(title_val) # 打印最终提取结果 print(result) # 用完记得关闭浏览器 driver.quit()
定位调试技巧
写代码之前先在浏览器里验证你的定位表达式是否正确,不要靠猜:
- 打开目标页面按F12打开开发者工具,切换到控制台tab
- 测试XPath表达式:输入
$x("你写的XPath路径")按回车 - 测试CSS选择器:输入
$("你写的CSS选择器")按回车
如果控制台返回的元素列表里能看到你要找的目标ul/li,再把对应的表达式写到代码里,能省很多调试时间。
内容的提问来源于stack exchange,提问作者A B
相关产品推荐
相关产品推荐


