我正在结合使用 Selenium 和 Java 来学习自动化。对于这个特定问题,我尝试使用 Selenium 转到包含 PDF 的 Google Drive 链接,然后截取 PDF 的每一页的屏幕截图,然后将每个屏幕截图保存在用户可以自己命名的文件中。问题是它截取第一页的屏幕截图,而不是向下滚动到 PDF 的每一页。这是我正在使用的测试链接(https://drive.google.com/file/d/1optp32jv20rvyiSBcCdI_a7C1jRR1UT4/view)。
下面是我正在使用的代码:
package googleDriveScreenshotTest;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.io.FileHandler;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.util.Scanner;
public class PdfScreenShotTest2{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Get user inputs with validation
String pdfUrl = getUserInput(scanner, "Enter Google Drive PDF link: ");
String folderName = getUserInput(scanner, "Enter folder name to save images: ");
int totalPages = getValidPageCount(scanner);
// Setup WebDriver
WebDriver driver = new ChromeDriver();
try {
// Create directory with error handling
File screenshotDir = createScreenshotDirectory(folderName);
// Navigate to PDF
driver.get(pdfUrl);
driver.manage().window().maximize();
// Wait for document to load
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15));
WebElement body = wait.until(ExpectedConditions.elementToBeClickable(By.tagName("body")));
// Click anywhere on page
body.click();
// Take screenshots of each page
for (int pageNumber = 1; pageNumber <= totalPages; pageNumber++) {
File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
File destination = new File(screenshotDir + "/page_" + pageNumber + ".png");
try {
FileHandler.copy(screenshot, destination);
System.out.println("Saved: " + destination.getAbsolutePath());
if (pageNumber < totalPages) {
body.sendKeys(Keys.PAGE_DOWN);
Thread.sleep(2000); // Allow time for scrolling
}
} catch (IOException e) {
System.err.println("Error saving screenshot for page " + pageNumber + ": " + e.getMessage());
}
}
} catch (Exception e) {
System.err.println("An error occurred: " + e.getMessage());
} finally {
driver.quit();
scanner.close();
}
}
private static String getUserInput(Scanner scanner, String prompt) {
while (true) {
System.out.print(prompt);
String input = scanner.nextLine().trim();
if (!input.isEmpty()) {
return input;
}
System.out.println("Input cannot be empty. Please try again.");
}
}
private static int getValidPageCount(Scanner scanner) {
while (true) {
try {
System.out.print("Enter number of pages in PDF: ");
int count = scanner.nextInt();
scanner.nextLine(); // Consume newline
if (count > 0) {
return count;
}
System.out.println("Please enter a positive number.");
} catch (Exception e) {
System.err.println("Invalid input. Please enter a valid number.");
scanner.nextLine(); // Clear invalid input
}
}
}
private static File createScreenshotDirectory(String folderName) throws IOException {
String downloadPath = System.getProperty("user.home") + "/Downloads/" + folderName;
File folder = new File(downloadPath);
if (!folder.exists()) {
if (!folder.mkdirs()) {
throw new IOException("Failed to create directory: " + downloadPath);
}
}
return folder;
}
}
您的问题可能源于Google Drive 的 PDF 查看器使用基于画布的渲染系统,这会阻止 Selenium 与各个页面正确交互。
这种
Keys.PAGE_DOWN
方法不可靠,因为 Google Drive 可能无法正确注册它,或者在截取下一个屏幕截图之前 PDF 可能无法完全加载。有几种“查看器”将自己“描述”为“PDF”预览器,但描述得非常笼统。它们的意思是,它们下载的是复制的文本和图像,这些文本和图像模拟了云存储/安全的 PDF 的部分内容。
Firefox 中使用的 PDF.JS 是主要示例。不过,Google 和 Microsoft 以及许多其他云服务查看器也做了类似的事情。
我们可以看到这不是 PDF,因为在检查过程中,内容显然是 PNG,并且在放大和缩小时会以不同的比例调整大小。
因此,对于 62 页的文档,需要滚动整个文档并将 blob 从检查器保存为图像,并以尽可能大的屏幕尺寸来保证质量。
当您拥有全部 62 个 blob 时,您需要保存包含文本和随机数位置的 HTML 页面,或通过目视检查手动重新编号。
因此,可以重建 pseudo.pdf,但除非删除源,否则这真的不值得付出努力。
这并不像我想象的那么简单。我发现这个页面上的所有 JS 滚动方法都不起作用。我没有截取页面的屏幕截图,而是截取了与幻灯片相对应的每个 IMG 标签的屏幕截图。这也会滚动页面,所以……
下面的代码可以工作……它会截取每张幻灯片的屏幕截图。它首先解析显示 PDF 页数的控件,然后循环遍历每个 IMG 标签并截取屏幕截图。您可能想要更改输出路径。