Selenium抓取非可视区域元素文本为空的解决方法
问题根因
空值问题确实和元素可视状态直接相关:
- Selenium的
.text属性严格遵循浏览器可见文本规则,仅会返回当前处于可视区域、未被CSS属性(visibility:hidden/display:none/偏移出视口)隐藏的元素文本。Swiper轮播组件默认会将非激活状态的slide通过CSS transform偏移到可视区域外,部分配置下还会对未激活slide的子节点做隐藏处理,这类元素调用.text只能拿到空字符串。 - 添加
--start-maximized参数后返回全空列表,是因为窗口尺寸变化触发Swiper执行响应式重算,轮播内容的渲染时机发生变化,页面加载完成后立即读取元素时,促销卡片的文本还未完成DOM注入。 - Swiper开启循环模式时会自动生成带有
swiper-slide-duplicate类名的占位节点,这些节点本身没有真实业务内容,也会被计入swiper-slide类元素的匹配结果。
修复方案
不需要将元素滚动到可视区域——这类操作会触发轮播切换动画,反而会提升抓取的不稳定性,直接按以下逻辑修改即可:
- 替换文本取值逻辑:通过执行Javascript读取DOM节点的
textContent属性,该属性直接从DOM树获取文本内容,完全不受元素可视状态、CSS隐藏规则的影响。 - 增加显式等待:不要仅依赖全局隐式等待,等首个促销卡片的内容渲染完成后再开始批量抓取,避免拿到未完成渲染的空节点。
- 过滤无效节点:遍历过程中跳过Swiper生成的重复占位slide,最终结果再过滤一遍空值项,避免无效数据。
- 固定启动窗口尺寸:避免响应式重算导致的渲染时机错乱问题。
修正后可运行代码
from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def get_promotion(): ''' Web scraping process to get Smiles promotion ''' promotions = [] chrome_options = Options() chrome_options.add_argument("--disable-notifications") # 固定窗口尺寸,避免触发Swiper响应式重算 chrome_options.add_argument("--window-size=1366,768") driver = webdriver.Chrome(options=chrome_options) driver.implicitly_wait(10) driver.get('https://www.smiles.com.br/home') # 显式等待促销卡片内容渲染完成,最长等待15秒 WebDriverWait(driver, 15).until( EC.presence_of_element_located((By.CSS_SELECTOR, '.swiper-slide h3')) ) site_promotion = driver.find_elements(By.CLASS_NAME, 'swiper-slide') for promotion in site_promotion: # 过滤Swiper循环模式生成的重复占位节点 slide_class = promotion.get_attribute('class') if 'swiper-slide-duplicate' in slide_class: continue # 定位各字段元素 destination_el = promotion.find_element(By.XPATH, './a/div/div/h3') origin_el = promotion.find_element(By.XPATH, './a/div/div/h4/span[2]') diamont_value_el = promotion.find_element(By.XPATH, './a/div/div/div/span[2]/p[3]') normal_value_el = promotion.find_element(By.XPATH, './a/div/div/div/span[2]/p[2]') # 通过JS读取textContent,无视口可见要求,同时去除首尾空白字符 promotions.append( { 'destination': driver.execute_script('return arguments[0].textContent.trim()', destination_el), 'origin': driver.execute_script('return arguments[0].textContent.trim()', origin_el), 'diamont_value': driver.execute_script('return arguments[0].textContent.trim()', diamont_value_el), 'normal_value': driver.execute_script('return arguments[0].textContent.trim()', normal_value_el), } ) # 二次过滤空内容的无效条目 promotions = [item for item in promotions if item['destination']] driver.quit() return promotions
内容的提问来源于stack exchange,提问作者Gabriel Braico Dornas
相关产品推荐
相关产品推荐

