Перед извлечением данных важно проанализировать HTML-структуру:
<table>
или div-структуру// Получаем все строки таблицы
List<WebElement> rows = driver.findElements(By.cssSelector("table#dataTable tbody tr"));
for (WebElement row : rows) {
// Получаем все ячейки в строке
List<WebElement> cells = row.findElements(By.tagName("td"));
// Извлекаем текст из каждой ячейки
for (WebElement cell : cells) {
System.out.print(cell.getText() + " | ");
}
System.out.println();
}
Прокрутка до загрузки всех данных:
WebElement table = driver.findElement(By.id("dynamicTable"));
long lastHeight = ((JavascriptExecutor)driver).executeScript("return arguments[0].scrollHeight", table);
while (true) {
((JavascriptExecutor)driver).executeScript("arguments[0].scrollTo(0, arguments[0].scrollHeight)", table);
Thread.sleep(1000); // Ожидание загрузки
long newHeight = ((JavascriptExecutor)driver).executeScript("return arguments[0].scrollHeight", table);
if (newHeight == lastHeight) break;
lastHeight = newHeight;
}
List<DataRecord> allData = new ArrayList<>();
do {
// Чтение данных с текущей страницы
List<WebElement> rows = driver.findElements(By.cssSelector(".data-row"));
for (WebElement row : rows) {
// Парсинг данных строки
DataRecord record = parseRow(row);
allData.add(record);
}
// Переход на следующую страницу
try {
driver.findElement(By.cssSelector(".next-page:not(.disabled)")).click();
wait.until(ExpectedConditions.stalenessOf(rows.get(0)));
} catch (NoSuchElementException e) {
break; // больше нет страниц
}
} while (true);
// Получение данных из конкретного столбца по имени заголовка
String headerXpath = "//table//th[contains(., '%s')]";
String columnName = "Price";
int colIndex = driver.findElements(By.xpath(String.format(headerXpath, columnName))).size();
List<String> prices = new ArrayList<>();
List<WebElement> rows = driver.findElements(By.xpath("//table/tbody/tr"));
for (int i = 1; i <= rows.size(); i++) {
String cellXpath = String.format("//table/tbody/tr[%d]/td[%d]", i, colIndex);
String price = driver.findElement(By.xpath(cellXpath)).getText();
prices.add(price);
}
// Ожидание появления хотя бы одной строки
wait.until(ExpectedConditions.numberOfElementsToBeMoreThan(By.cssSelector(".table-row"), 0));
// Использование частичного совпадения атрибутов
List<WebElement> rows = driver.findElements(By.cssSelector("div[class*='table-row-']"));
// Получение данных-атрибутов
String dataId = row.getAttribute("data-id");
// Извлечение вложенных элементов
WebElement nested = cell.findElement(By.cssSelector(".nested-element"));
Кэширование элементов:
WebElement table = driver.findElement(By.id("mainTable"));
// Дальнейшие поиски только внутри таблицы
List<WebElement> rows = table.findElements(By.cssSelector("tr"));
Пакетное чтение данных:
JavascriptExecutor js = (JavascriptExecutor)driver;
List<String> allData = (List<String>)js.executeScript(
"return Array.from(document.querySelectorAll('table tr')).map(row => row.innerText);"
);
Параллельная обработка (для больших таблиц):
rows.parallelStream().forEach(row -> processRow(row));
public class TableData {
private String name;
private BigDecimal price;
private LocalDate date;
// геттеры/сеттеры
}
List<TableData> tableData = new ArrayList<>();
// заполнение данных при парсинге
try (PrintWriter writer = new PrintWriter("output.csv")) {
for (TableData data : tableData) {
writer.println(data.toCsvString());
}
}
jdbcTemplate.batchUpdate(
"INSERT INTO table_data (name, price) VALUES (?, ?)",
tableData.stream()
.map(data -> new Object[]{data.getName(), data.getPrice()})
.collect(Collectors.toList())
);
Профессиональный совет: Для сложных таблиц создайте класс-обертку TableReader с методами getColumnValues(), getRowData(), filterRows() и т.д., который будет инкапсулировать логику работы с конкретной таблицей в вашем приложении.