You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Selenium Java获取印度人口SVG图表1951-2024年悬停数据

问题描述

需要抓取印度人口折线图(1951-2024年)的年度数据,通过Selenium的moveToElement()悬停SVG元素时失效,无法触发tooltip获取数据。当前代码尝试通过SVG矩形坐标移动鼠标,但没有效果。

问题原因与解决方案

1. SVG元素定位错误

原代码定位的rect是图表背景容器,并非折线图的可交互数据点。该网站用Highcharts生成图表,实际触发tooltip的是折线的path元素或数据点circle元素,必须定位到这些可交互元素才能触发悬停事件。

2. 坐标计算逻辑错误

moveToElement(WebElement element, int xOffset, int yOffset)的偏移量是相对于元素左上角的坐标,原代码计算出的负数偏移会把鼠标移出元素范围,自然无法触发交互。

3. 正确实现思路

  • 定位到Highcharts生成的折线path元素(核心交互区域)
  • 根据年份跨度(1951-2024共74年)计算鼠标移动步长,遍历每个数据点位置
  • 每次移动后抓取页面上的HTML tooltip数据(该网站tooltip是独立的HTML元素,不是SVG内部元素)
修改后的完整代码
package selenium_concepts.SVGElements;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import java.time.Duration;
import java.util.List;

public class IndianPopulationSVGElementTest {
    WebDriver driver;
    JavascriptExecutor jse;

    @BeforeTest
    public void setup() {
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        driver.manage().deleteAllCookies();
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(20));
        driver.get("https://www.worldometers.info/world-population/india-population/");
    }

    @Test(description = "India Population Graph data test")
    public void svgGraphIndiaPopulation() throws InterruptedException {
        jse = ((JavascriptExecutor) driver);
        // 定位到SVG图表容器,滚动到可见区域
        WebElement svgContainer = driver.findElement(By.xpath("//*[local-name()='svg' and @id='chartContainer']"));
        jse.executeScript("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", svgContainer);
        Thread.sleep(2000);

        // 获取页面基础信息
        String heading = driver.findElement(By.cssSelector("#maincounter-wrap h1")).getText();
        String totalPopulationIndia = driver.findElement(By.cssSelector(".maincounter-number span")).getText();
        String indianPopulationBetweenYear = driver.findElement(By.xpath("(//div[@class='chart-header'])[1]")).getText();
        
        System.out.println("-------------- " + heading + " ----------------- ");
        System.out.println("Total Population India: " + totalPopulationIndia);
        System.out.println("Between Years: " + indianPopulationBetweenYear);

        // 定位到折线图的路径元素(可触发tooltip的交互区域)
        WebElement linePath = driver.findElement(By.xpath("//*[local-name()='svg']//*[name()='path' and contains(@class, 'highcharts-graph')]"));
        Actions actions = new Actions(driver);

        // 获取路径元素的位置和尺寸,计算遍历步长
        int pathWidth = linePath.getSize().getWidth();
        // 1951到2024共74年,设置步长适配数据点数量
        int step = pathWidth / 73;

        // 遍历每个数据点位置
        for (int i = 0; i <= pathWidth; i += step) {
            // 移动鼠标到路径上的对应位置(相对于元素左上角的偏移)
            actions.moveToElement(linePath, i, 0).perform();
            Thread.sleep(500);

            // 抓取tooltip中的数据
            try {
                List<WebElement> tooltipTexts = driver.findElements(By.xpath("//*[local-name()='div' and contains(@class, 'highcharts-tooltip')]//span"));
                if (!tooltipTexts.isEmpty()) {
                    String year = tooltipTexts.get(0).getText();
                    String population = tooltipTexts.get(1).getText();
                    System.out.println(year + " -> " + population);
                }
            } catch (NoSuchElementException e) {
                System.out.println("Tooltip not found at position: " + i);
            }
        }
    }

    @AfterTest
    public void tearDown() throws InterruptedException {
        Thread.sleep(2000);
        driver.quit();
    }
}
关键说明
  • 替换原有的rect定位,改为定位折线图的path元素(Highcharts生成的可交互折线)
  • 按年份跨度计算移动步长,确保每个数据点都能被覆盖
  • 抓取独立的HTML tooltip元素,而非SVG内部元素(该网站tooltip采用HTML渲染)
  • 增加异常处理,避免因tooltip加载延迟导致的元素未找到错误

内容的提问来源于stack exchange,提问作者Ravi Lohana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:30:54