使用Python Selenium提取SVG提示框内容遇点击拦截问题
从地理图表悬停提示框提取文本的问题
我花了两天时间尝试从以下页面的地理图表提示框提取文本值:https://exportpotential.intracen.org/en/markets/geo-map?fromMarker=i&exporter=4&whatMarker=ls&what=6&toMarker=j
提示框仅在鼠标悬停时可见,我尝试点击对应元素获取值,但部分元素无法点击。使用的代码如下:
all_nodes = driver.find_element(By.CSS_SELECTOR, ".flamingo.chart").find_elements(By.CSS_SELECTOR, ".node") for node in all_nodes: node.find_element(By.CSS_SELECTOR, ".circle.total").click() country = driver.find_element(By.CSS_SELECTOR, ".tooltip-title").text.strip()
运行代码时出现如下错误:
Message: element click intercepted: Element <circle class="circle total IND" cx="0" cy="0" r="65" style="fill: rgba(158, 106, 117, 0.6);"></circle> is not clickable at point (830, 543). Other element would receive the click: <circle class="circle perc IRQ" cx="0" cy="0" r="61.56828206861062" style="fill: rgb(158, 106, 117);"></circle> (Session info: chrome=114.0.5735.133) Stacktrace: 0 chromedriver 0x000000010c8d56b8 chromedriver + 4937400 1 chromedriver 0x000000010c8ccb73 chromedriver + 4901747 2 chromedriver 0x000000010c48a616 chromedriver + 435734 3 chromedriver 0x000000010c4d5b97 chromedriver + 744343 4 chromedriver 0x000000010c4d3450 chromedriver + 734288 5 chromedriver 0x000000010c4d0a84 chromedriver + 723588 6 chromedriver 0x000000010c4cfbe4 chromedriver + 719844 7 chromedriver 0x000000010c4c21e1 chromedriver + 664033 8 chromedriver 0x000000010c4f2012 chromedriver + 860178 9 chromedriver 0x000000010c4c19c1 chromedriver + 661953 10 chromedriver 0x000000010c4f21ce chromedriver + 860622 11 chromedriver 0x000000010c50ce76 chromedriver + 970358 12 chromedriver 0x000000010c4f1de3 chromedriver + 859619 13 chromedriver 0x000000010c4bfd7f chromedriver + 654719 14 chromedriver 0x000000010c4c10de chromedriver + 659678 15 chromedriver 0x000000010c8912ad chromedriver + 4657837 16 chromedriver 0x000000010c896130 chromedriver + 4677936 17 chromedriver 0x000000010c89cdef chromedriver + 4705775 18 chromedriver 0x000000010c89705a chromedriver + 4681818 19 chromedriver 0x000000010c86992c chromedriver + 4495660 20 chromedriver 0x000000010c8b4838 chromedriver + 4802616 21 chromedriver 0x000000010c8b49b7 chromedriver + 4802999 22 chromedriver 0x000000010c8c599f chromedriver + 4872607 23 libsystem_pthread.dylib 0x00007fff2050c8fc _pthread_start + 224 24 libsystem_pthread.dylib 0x00007fff20508443 thread_start + 15
解决方法
1. 模拟鼠标悬停(贴合页面触发逻辑)
点击会触发元素层级拦截,而提示框本身是悬停触发,改用ActionChains模拟悬停:
from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC all_nodes = driver.find_element(By.CSS_SELECTOR, ".flamingo.chart").find_elements(By.CSS_SELECTOR, ".node") wait = WebDriverWait(driver, 10) action = ActionChains(driver) for node in all_nodes: circle = node.find_element(By.CSS_SELECTOR, ".circle.total") # 模拟鼠标悬停触发提示框 action.move_to_element(circle).perform() # 等待提示框可见后获取文本 country = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".tooltip-title"))).text.strip() print(country)
2. 用JavaScript强制触发悬停事件(绕过遮挡)
如果悬停仍被上层元素拦截,直接通过JS触发目标元素的mouseover事件:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC all_nodes = driver.find_element(By.CSS_SELECTOR, ".flamingo.chart").find_elements(By.CSS_SELECTOR, ".node") wait = WebDriverWait(driver, 10) for node in all_nodes: circle = node.find_element(By.CSS_SELECTOR, ".circle.total") # 调用JS触发悬停事件 driver.execute_script("arguments[0].dispatchEvent(new MouseEvent('mouseover', {bubbles: true}));", circle) # 获取提示框文本 country = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".tooltip-title"))).text.strip() print(country)
3. 直接从元素属性/页面数据源提取(更高效)
这类图表的数据通常会存在于元素属性或页面JS变量中,无需触发提示框:
all_nodes = driver.find_element(By.CSS_SELECTOR, ".flamingo.chart").find_elements(By.CSS_SELECTOR, ".node") for node in all_nodes: # 从node元素的class中提取国家代码(比如IND、IRQ) country_code = [cls for cls in node.get_attribute("class").split() if len(cls)==3][0] # 或者查找是否有隐藏的名称节点 country_name = node.find_element(By.CSS_SELECTOR, ".country-name").text.strip() print(country_name, country_code)
内容的提问来源于stack exchange,提问作者Mahdi
相关产品推荐
相关产品推荐

