使用Selenium爬取valorinveste.globo.com时遭遇ElementClickInterceptedException
问题解决:爬取Valor Investe新闻时的弹窗遮挡问题
问题描述
爬取https://valorinveste.globo.com/ultimas-noticias/时,点击底部紫色"Veja Mais"按钮加载更多新闻,但滚动页面时会随机弹出通知窗口/广告,导致按钮被遮挡,抛出ElementClickInterceptedException。常规等待弹窗的方法无效,因为弹窗随滚动动态加载。
解决方案
针对动态弹窗遮挡的问题,可通过以下几种方式解决:
1. 用JavaScript直接触发按钮点击
直接通过JS执行点击操作,绕过元素遮挡的问题,这是最直接的解决方式。
2. 动态检测并关闭弹窗
在每次点击前检查是否有弹窗出现,若有则关闭,避免遮挡。
3. 优化ChromeOptions,提前屏蔽弹窗和广告
通过浏览器配置减少弹窗和广告的加载,从源头降低遮挡概率。
4. 等待按钮处于可点击状态
将等待条件从presence_of_element_located改为element_to_be_clickable,确保按钮不仅存在还能被点击。
修改后的代码
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 import time from bs4 import BeautifulSoup # 配置Chrome选项,屏蔽弹窗、广告和通知 options = webdriver.ChromeOptions() # 禁用通知 options.add_argument("--disable-notifications") # 屏蔽新弹窗内容 options.add_argument("--block-new-web-contents") # 禁用弹窗拦截提示 options.add_argument("--disable-popup-blocking") driver = webdriver.Chrome(options=options) def wait_for_element_location_to_be_stable(element): initial_location = element.location previous_location = initial_location start_time = time.time() while time.time() - start_time < 1: current_location = element.location if current_location != previous_location: previous_location = current_location start_time = time.time() time.sleep(0.4) def close_popups(): # 关闭可能出现的弹窗(根据实际弹窗元素调整选择器) popup_selectors = [ "//button[contains(@class, 'close') or contains(text(), 'Fechar')]", "//div[contains(@class, 'modal-close')]" ] for selector in popup_selectors: try: popup = WebDriverWait(driver, 2).until(EC.element_to_be_clickable((By.XPATH, selector))) popup.click() except: pass # 没有弹窗就跳过 driver.get("https://valorinveste.globo.com/ultimas-noticias/") driver.maximize_window() wait = WebDriverWait(driver, 10) # 处理Cookie同意弹窗 consent = wait.until(EC.element_to_be_clickable((By.XPATH, "//button[@class='cookie-banner-lgpd_accept-button']"))) consent.click() for _ in range(2): for _ in range(6): load_more = wait.until(EC.element_to_be_clickable((By.XPATH, "//div[@class='load-more gui-color-primary-bg']//a"))) dates = wait.until(EC.presence_of_all_elements_located((By.XPATH, "//span[@class='feed-post-datetime']"))) driver.execute_script('arguments[0].scrollIntoView(true);', dates[-1]) wait_for_element_location_to_be_stable(load_more) # 滚动后检查并关闭弹窗 close_popups() # 点击加载更多,优先用JS点击避免遮挡 try: load_more.click() except: # 若被遮挡,用JS直接触发点击 driver.execute_script("arguments[0].click();", load_more) # 获取页面源码后再退出驱动 page_source = driver.page_source driver.quit() soup = BeautifulSoup(page_source, "html.parser")
关键改进说明
- ChromeOptions优化:添加参数禁用通知、弹窗,减少弹窗出现概率。
- 动态关闭弹窗:在滚动后增加
close_popups函数,检测并关闭可能出现的弹窗,避免遮挡按钮。 - JS点击兜底:当常规点击失败时,用
execute_script直接触发按钮的点击事件,绕过元素遮挡问题。 - 等待条件优化:将Cookie按钮和加载更多按钮的等待条件改为
element_to_be_clickable,确保元素可交互。
内容的提问来源于stack exchange,提问作者Carlos Eduardo Barros
相关产品推荐
相关产品推荐

