0

0

Java Selenium:实现CSV数据与Web表格的精准比对与验证

碧海醫心

碧海醫心

发布时间:2025-09-27 12:53:01

|

841人浏览过

|

来源于php中文网

原创

Java Selenium:实现CSV数据与Web表格的精准比对与验证

本文旨在提供一个在Java中使用Selenium框架比对CSV文件数据与网页表格内容的专业教程。我们将探讨常见的CSV解析陷阱,并介绍一种更健壮的CSV读取方法。教程将涵盖Web表格数据的提取、CSV数据的解析,以及如何将两者进行有效比对和验证,确保测试的准确性和稳定性。

在自动化测试或数据验证场景中,经常需要将外部数据源(如csv文件)与网页上显示的表格数据进行比对。这不仅要求熟练掌握selenium对web元素的定位和操作,还需要对csv文件解析有深入的理解。不恰当的csv解析方法可能导致数据错位或indexoutofboundsexception等问题,尤其是在处理包含特殊字符(如逗号)或引号的字段时。

一、Web表格数据的提取

使用Selenium从网页中提取表格数据是比对操作的第一步。我们需要定位到目标表格,然后遍历其行和列来获取每个单元格的文本内容。

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import java.util.ArrayList;
import java.util.List;

public class WebTableExtractor {

    /**
     * 从指定的Web表格中提取所有数据
     * @param driver WebDriver实例
     * @param tableLocator 表格的定位器(例如 By.cssSelector("#dStocks1"))
     * @return 包含表格所有数据的List>,每个内部List代表一行
     */
    public static List> extractTableData(WebDriver driver, By tableLocator) {
        List> tableData = new ArrayList<>();
        WebElement webTable = driver.findElement(tableLocator);

        // 定位表格的所有行
        List rows = webTable.findElements(By.tagName("tr"));

        // 遍历每一行
        for (int i = 0; i < rows.size(); i++) {
            List rowData = new ArrayList<>();
            WebElement row = rows.get(i);

            // 定位当前行的所有单元格(td或th)
            // 通常第一行可能是表头(th),其余行是数据(td)
            List cells = row.findElements(By.tagName("td"));
            if (cells.isEmpty()) { // 如果没有td,尝试找th (表头)
                cells = row.findElements(By.tagName("th"));
            }

            // 遍历每个单元格并提取文本
            for (WebElement cell : cells) {
                rowData.add(cell.getText().trim()); // .trim() 清除前后空格
            }
            tableData.add(rowData);
        }
        return tableData;
    }
}

注意事项:

ImgGood
ImgGood

免费在线AI照片编辑器

下载

立即学习Java免费学习笔记(深入)”;

  • 定位器准确性: 确保tableLocator能唯一且稳定地定位到目标表格。
  • 表头处理: 上述代码同时处理了和 ,但如果表头不需要比对,可以在循环中跳过第一行或根据实际情况调整。
  • 空值与格式: 提取出的文本可能包含空格或特定格式,后续比对时需要进行统一处理。
  • 二、健壮的CSV数据读取

    传统的String.split(",")方法在处理CSV文件时常常遇到问题,例如字段中包含逗号(被双引号包围)或换行符。为了避免IndexOutOfBoundsException和其他解析错误,推荐使用更专业的CSV解析方法。这里我们使用Scanner类来处理,它能更灵活地定义分隔符。对于更复杂的CSV结构,可以考虑使用Apache Commons CSV或OpenCSV等第三方库。

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Scanner;
    
    public class CsvDataReader {
        // 定义CSV分隔符
        private static final String COMMA_DELIMITER = ",";
    
        /**
         * 从一行CSV文本中解析出字段列表
         * @param line 单行CSV文本
         * @return 包含该行所有字段的List
         */
        private static List getRecordFromLine(String line) {
            List values = new ArrayList<>();
            // 使用Scanner解析一行,并指定逗号为分隔符
            // 注意:此简单实现对带引号的逗号处理有限,更复杂场景建议用第三方库
            try (Scanner rowScanner = new Scanner(line)) {
                rowScanner.useDelimiter(COMMA_DELIMITER);
                while (rowScanner.hasNext()) {
                    String value = rowScanner.next().trim();
                    // 移除可能存在的双引号,如果字段被双引号包裹
                    if (value.startsWith("\"") && value.endsWith("\"") && value.length() > 1) {
                        value = value.substring(1, value.length() - 1);
                    }
                    values.add(value);
                }
            }
            return values;
        }
    
        /**
         * 读取整个CSV文件并解析所有数据
         * @param filePath CSV文件路径
         * @param skipHeader 是否跳过CSV文件的第一行(通常是表头)
         * @return 包含所有CSV数据的List>,每个内部List代表一行
         * @throws FileNotFoundException 如果文件不存在
         */
        public static List> readCsvData(String filePath, boolean skipHeader) throws FileNotFoundException {
            List> records = new ArrayList<>();
            try (Scanner scanner = new Scanner(new File(filePath))) {
                if (skipHeader && scanner.hasNextLine()) {
                    scanner.nextLine(); // 跳过表头
                }
                while (scanner.hasNextLine()) {
                    records.add(getRecordFromLine(scanner.nextLine()));
                }
            }
            return records;
        }
    
        public static void main(String[] args) throws FileNotFoundException {
            // 示例用法
            // 假设您的CSV文件位于 src/test/resources/test.csv
            String csvFilePath = "src/test/resources/test.csv";
            List> csvRecords = readCsvData(csvFilePath, true); // 跳过表头
            System.out.println("CSV Data:");
            csvRecords.forEach(System.out::println);
    
            /*
            假设 test.csv 内容如下:
            Header1,Header2,Header3
            data1,"data,with,comma",data3
            data4,data5,data6
            */
            // 输出示例:
            // CSV Data:
            // [data1, data,with,comma, data3]
            // [data4, data5, data6]
        }
    }

    注意事项:

    立即学习Java免费学习笔记(深入)”;

    • Scanner的局限性: 尽管Scanner比String.split更优,但它对复杂CSV格式(如多行字段、转义双引号)的处理仍有局限。对于生产级应用,强烈推荐使用如Apache Commons CSV或OpenCSV等成熟的CSV解析库。
    • 文件路径: 确保filePath是正确的,并且文件存在。
    • 表头处理: readCsvData方法提供了skipHeader参数,可灵活选择是否跳过CSV文件的第一行。
    • 数据清洗 getRecordFromLine中加入了trim()和简单的双引号移除逻辑,以提高数据一致性。

    三、数据比对与验证逻辑

    在分别获取了Web表格数据和CSV数据后,下一步就是进行逐行逐列的比对。通常,我们会使用测试框架(如JUnit或TestNG)的断言来验证数据的一致性。

    import org.junit.Assert; // 引入JUnit断言,如果是TestNG则使用 org.testng.Assert
    
    public class DataComparator {
    
        /**
         * 比对Web表格数据和CSV数据
         * @param webTableData 从Web表格提取的数据
         * @param csvData 从CSV文件读取的数据
         * @param ignoreHeaderWebTable 是否忽略Web表格的第一行(通常是表头)
         * @param ignoreHeaderCsv 是否忽略CSV数据的第一行(通常是表头)
         */
        public static void compareData(List> webTableData, List> csvData,
                                       boolean ignoreHeaderWebTable, boolean ignoreHeaderCsv) {
    
            List> actualData = new ArrayList<>(webTableData);
            List> expectedData = new ArrayList<>(csvData);
    
            if (ignoreHeaderWebTable && !actualData.isEmpty()) {
                actualData.remove(0); // 移除Web表格的表头
            }
            if (ignoreHeaderCsv && !expectedData.isEmpty()) {
                expectedData.remove(0); // 移除CSV数据的表头
            }
    
            // 1. 验证行数是否一致
            Assert.assertEquals("Web表格和CSV数据的行数不一致!", expectedData.size(), actualData.size());
    
            // 2. 逐行逐列比对数据
            for (int i = 0; i < expectedData.size(); i++) {
                List expectedRow = expectedData.get(i);
                List actualRow = actualData.get(i);
    
                // 验证列数是否一致
                Assert.assertEquals("第 " + (i + 1) + " 行的列数不一致!", expectedRow.size(), actualRow.size());
    
                // 逐个单元格比对
                for (int j = 0; j < expectedRow.size(); j++) {
                    String expectedCell = expectedRow.get(j);
                    String actualCell = actualRow.get(j);
    
                    // 可以在这里添加数据清洗或格式化逻辑,例如:
                    // expectedCell = expectedCell.replace(",", "").trim(); // 移除逗号,去除空格
                    // actualCell = actualCell.replace(",", "").trim();
                    // 如果是数字比对,可以转换为数值类型再比对
                    // Assert.assertEquals(Double.parseDouble(expectedCell), Double.parseDouble(actualCell), 0.001);
    
                    Assert.assertEquals("第 " + (i + 1) + " 行,第 " + (j + 1) + " 列的数据不一致!",
                                        expectedCell, actualCell);
                    System.out.println("数据匹配:行 " + (i + 1) + ", 列 " + (j + 1) + " - 预期: " + expectedCell + ", 实际: " + actualCell);
                }
            }
            System.out.println("Web表格数据与CSV数据完全匹配!");
        }
    }

    注意事项:

    立即学习Java免费学习笔记(深入)”;

    • 断言库: 根据您使用的测试框架选择合适的断言库(JUnit的org.junit.Assert或TestNG的org.testng.Assert)。
    • 数据清洗与格式化: 这是比对过程中最关键的一步。Web页面上的数据可能经过格式化(如货币符号、千位分隔符、日期格式),而CSV文件中的数据可能是原始格式。务必在比对前对两者进行统一的清洗和格式化处理,例如:
      • 移除空格 (.trim())。
      • 移除特殊字符(如 $, ,)。
      • 统一日期格式。
      • 将字符串转换为数字类型进行数值比对。
    • 错误信息: 断言的错误信息应清晰明了,指出哪个位置的数据不匹配,以便于调试。
    • 行/列偏移: 确保在比对时正确处理了表头,避免因表头导致的数据错位。

    四、整合与完整示例

    将上述三个部分整合到一个测试用例中,可以形成一个完整的Web表格与CSV数据比对流程。

    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.chrome.ChromeDriver;
    
    import java.io.FileNotFoundException;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    public class WebTableCsvComparisonTest {
    
        private WebDriver driver;
        private static final String CSV_FILE_PATH = "src/test/resources/test_data.csv"; // 假设CSV文件路径
        private static final String WEB_PAGE_URL = "http://your-web-application.com/table_page"; // 假设网页URL
    
        @Before
        public void setUp() {
            // 设置WebDriver路径,例如ChromeDriver
            System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
            driver = new ChromeDriver();
            driver.manage().window().maximize();
            driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
            driver.get(WEB_PAGE_URL); // 导航到包含Web表格的页面
        }
    
        @Test
        public void testWebTableDataMatchesCsv() throws FileNotFoundException {
            // 1. 从Web表格中提取数据
            // 假设Web表格的CSS选择器是 #dStocks1
            List> webTableData = WebTableExtractor.extractTableData(driver, By.cssSelector("#dStocks1"));
            System.out.println("提取到的Web表格数据:");
            webTableData.forEach(System.out::println);
    
            // 2. 从CSV文件中读取数据
            // 假设CSV文件有表头,需要跳过
            List> csvData = CsvDataReader.readCsvData(CSV_FILE_PATH, true);
            System.out.println("\n读取到的CSV数据:");
            csvData.forEach(System.out::println);
    
            // 3. 比对Web表格数据和CSV数据
            // Web表格和CSV数据都假设包含表头,但在比对时我们选择忽略它们
            DataComparator.compareData(webTableData, csvData, true, false); // Web表格忽略表头,CSV数据已经跳过表头,所以这里不再忽略
        }
    
        @After
        public void tearDown() {
            if (driver != null) {
                driver.quit();
            }
        }
    }

    示例CSV文件 src/test/resources/test_data.csv 内容:

    Header1,Header2,Header3,Header4
    ValueA1,ValueA2,ValueA3,ValueA4
    ValueB1,"Value,B2",ValueB3,ValueB4
    ValueC1,ValueC2,ValueC3,ValueC4

    示例Web表格(HTML结构):

    Header1 Header2 Header3 Header4
    ValueA1 ValueA2 ValueA3 ValueA4
    ValueB1 Value,B2 ValueB3 ValueB4
    ValueC1 ValueC2 ValueC3 ValueC4

    总结

    通过上述教程,我们提供了一个在Java中使用Selenium比对CSV数据与Web表格的完整解决方案。关键在于:

    1. Web表格数据提取: 使用Selenium准确遍历Web表格的行和列,提取单元格文本。
    2. 健壮的CSV解析: 采用Scanner或更专业的第三方库来处理CSV文件,避免常见解析错误。
    3. 细致的数据比对: 逐行逐列地比对数据,并考虑数据类型、格式和潜在的清洗需求。
    4. 清晰的断言: 利用测试框架的断言机制,提供明确的失败信息,便于问题定位。

    遵循这些最佳实践,可以显著提高自动化测试的准确性和稳定性,确保Web页面上的数据与预期数据源保持一致。在实际项目中,根据CSV文件的复杂度和性能要求,灵活选择CSV解析工具至关重要。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

832

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

738

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

734

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

398

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16925

2023.08.03

Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.9万人学习

CSS教程
CSS教程

共754课时 | 19.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号