使用Selenium的find_elements_by_xpath无法一次性获取全部href,求其他数据提取方法
Selenium抓取雅虎商城商品链接不全的解决方案
问题根因
你遇到的提取不全问题主要来自两个核心原因:
- 目标页面是滚动动态加载,首次打开仅加载首屏商品,剩余商品需要滚动到页面底部才会触发加载
- 你使用的
sc-eWvPqa cePswM是前端框架自动生成的hash类名,属于动态属性,页面更新后类名会发生变化,定位稳定性极低,同时Selenium 4+版本已经正式弃用find_elements_by_xpath这类写法,也可能引发兼容性问题。
可行解决方案
方案1:优化定位规则+模拟滚动加载全量内容
这是最小改动的适配方案,在原Selenium逻辑基础上调整即可:
!pip install selenium beautifulsoup4 from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.service import Service import time # 适配Selenium 4+的浏览器初始化写法 s = Service('./chromedriver.exe') browser = webdriver.Chrome(service=s) browser.implicitly_wait(8) browser.get("https://tw.mall.yahoo.com/store/%E5%B1%88%E8%87%A3%E6%B0%8FWatsons:watsons") # 模拟滚动加载全量商品 last_page_height = browser.execute_script("return document.body.scrollHeight") while True: # 滚动到页面底部 browser.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 等待商品加载完成 time.sleep(2) new_page_height = browser.execute_script("return document.body.scrollHeight") # 页面高度不再变化说明所有商品已加载完成 if new_page_height == last_page_height: break last_page_height = new_page_height # 改用稳定的定位规则,避开动态hash类名,直接匹配商品列表的a标签 product_links = browser.find_elements(By.XPATH, '//ul[contains(@class,"productGrid")]/li//a[@href]') # 提取所有href属性,过滤无效空链接 href_list = [link.get_attribute('href') for link in product_links if link.get_attribute('href')] print(f"共获取有效商品链接数:{len(href_list)}") print(href_list) browser.quit()
方案2:结合BeautifulSoup解析全量页面源码
如果XPath定位还是不稳定,可以直接拉取加载完成后的完整页面源码,用BeautifulSoup做解析提取:
from bs4 import BeautifulSoup # 接上面的滚动加载完成后的逻辑 page_source = browser.page_source soup = BeautifulSoup(page_source, 'lxml') # 用css选择器匹配所有商品a标签 product_a_tags = soup.select('ul[class*="productGrid"] li a[href]') href_list = [tag['href'] for tag in product_a_tags]
方案3:直接调用商品列表接口提取数据
比Selenium模拟效率更高的方案是直接抓页面的商品接口:
打开浏览器控制台的「网络」面板,筛选Fetch/XHR请求,找到商品列表的接口,直接构造请求拉取JSON格式的商品数据,无需模拟浏览器滚动,提取速度更快,也不会出现元素定位失效的问题。
注意事项
- 不要使用前端框架生成的动态hash类名做定位依据,这类属性每次页面发布都会变更,定位失败概率极高
- 隐式等待仅能保证元素首次出现,无法覆盖动态加载的全量内容,必须主动触发滚动操作才能拿到全部商品
- 建议升级到Selenium 4+版本,使用统一的
find_elements(By.定位类型, 路径)写法,避免弃用方法带来的报错
内容的提问来源于stack exchange,提问作者QQdingyen
相关产品推荐
相关产品推荐

