admin管理员组

文章数量:1406052

I am using Selenium and Java together to learn automation. For this specific problem, I am trying to use Selenium to go to a Google Drive link that contains a PDF and then take a screenshot of every single page of the PDF and then save each screenshot in a file the user can name themselves. The problem is that it is taking screenshots of the first page and not scrolling down to each individual page of the PDF. Here is the test link that I am working with().

Below is the code that I am using:

package googleDriveScreenshotTest;

import .openqa.selenium.*;
import .openqa.selenium.chrome.ChromeDriver;
import .openqa.selenium.io.FileHandler;
import .openqa.selenium.support.ui.ExpectedConditions;
import .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;
    }
}

I am using Selenium and Java together to learn automation. For this specific problem, I am trying to use Selenium to go to a Google Drive link that contains a PDF and then take a screenshot of every single page of the PDF and then save each screenshot in a file the user can name themselves. The problem is that it is taking screenshots of the first page and not scrolling down to each individual page of the PDF. Here is the test link that I am working with(https://drive.google/file/d/1optp32jv20rvyiSBcCdI_a7C1jRR1UT4/view).

Below is the code that I am using:

package googleDriveScreenshotTest;

import .openqa.selenium.*;
import .openqa.selenium.chrome.ChromeDriver;
import .openqa.selenium.io.FileHandler;
import .openqa.selenium.support.ui.ExpectedConditions;
import .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;
    }
}
Share Improve this question edited Mar 8 at 13:07 Mark Rotteveel 110k229 gold badges156 silver badges224 bronze badges asked Mar 6 at 16:55 Momo MauriceMomo Maurice 31 bronze badge 5
  • Maybe you could add the page number to the URL, e.g. https:// ... .pdf#page=2 opens the PDF scrolled to the second page. – howlger Commented Mar 6 at 17:17
  • 2 Why would you take pictures of the PDF? Why not just download it? – JeffC Commented Mar 6 at 18:55
  • @JeffC The reason I can not download it is because my professor does not allow anyone to download any of her pdf's. So I thought It would be a cool project to do, to learn about selenium. – Momo Maurice Commented Mar 6 at 19:22
  • 2 If you are viewing it, you can download it... you've already downloaded it. Anyway, this really has nothing to do with Selenium. Selenium automates browsers but cannot see into a PDF without other libraries. If you want to learn Selenium, there are much better ways to do so. – JeffC Commented Mar 6 at 20:05
  • @JeffC at least click the link to see if you can download it, because if you can then sorry for wasting your time – Momo Maurice Commented Mar 6 at 20:09
Add a comment  | 

3 Answers 3

Reset to default 1

Your issue likely stems from Google Drive's PDF viewer using a canvas-based rendering system, which prevents Selenium from interacting with individual pages properly.

The Keys.PAGE_DOWN approach is unreliable because Google Drive might not register it correctly, or the PDF might not fully load before the next screenshot is taken.


// Scroll and take screenshots
for (int pageNumber = 1; pageNumber <= totalPages; pageNumber++) {
    // Take screenshot
    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) {
            // Use JavaScript to scroll down
            JavascriptExecutor js = (JavascriptExecutor) driver;
            js.executeScript("window.scrollBy(0, window.innerHeight)");

            // Wait for the next page to render
            Thread.sleep(3000);
        }
    } catch (IOException e) {
        System.err.println("Error saving screenshot for page " + pageNumber + ": " + e.getMessage());
    }
}


This wasn't as easy as I thought it would be. I found that none of the JS scroll methods work on this page. Rather than taking a screenshot of the page, I took screenshots of each IMG tag that corresponds to a slide. This also scrolled the page, so...

The code below works... it takes a screenshot of each slide. It first parses the control that displays the number of pages in the PDF and then loops through each IMG tag and takes a screenshot of it. You'll likely want to change the output path.

import java.io.File;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;

import .apachemons.io.FileUtils;
import .openqa.selenium.By;
import .openqa.selenium.JavascriptExecutor;
import .openqa.selenium.OutputType;
import .openqa.selenium.WebDriver;
import .openqa.selenium.WebElement;
import .openqa.selenium.chrome.ChromeDriver;
import .openqa.selenium.support.ui.ExpectedConditions;
import .openqa.selenium.support.ui.WebDriverWait;

public class PdfScreenShotTest2 {
    public static void main(String[] args) throws Exception {
        String url = "https://drive.google/file/d/1optp32jv20rvyiSBcCdI_a7C1jRR1UT4/view";

        WebDriver driver = new ChromeDriver();
        driver.manage().window().maximize();
        driver.get(url);

        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        JavascriptExecutor js = (JavascriptExecutor) driver;

        // get last page number
        WebElement label = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("[aria-label^='Page 1 of']")));
        String fullLabel = label.getAttribute("aria-label");
        int lastPage = Integer.parseInt(fullLabel.substring(fullLabel.lastIndexOf(' ') + 1));

        // get screenshots of each slide
        List<WebElement> slides = wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("div[role='document'] img")));
        for (int i = 0; i < lastPage; i++) {
            File slideFile = slides.get(i).getScreenshotAs(OutputType.FILE);
            FileUtils.copyFile(slideFile, new File("c:\\temp\\slide" + i + ".png"));
            slides = wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("div[role='document'] img")));
        }

        driver.quit();
    }
}

There are several "Viewers" that "Describe" themselves very loosely as a "PDF" pre-viewer. What they mean is they download text and images that are reproduction emulating parts of a CLOUD STORED/SECURED PDF.

PDF.JS as used in Firefox is the primary example. However Google and Microsoft and many other cloud served viewers do similar.

We can see this is not a PDF since during inspection the contents are clearly PNG that resize at different scales on zoom in and out.

Thus for a 62 page document it needs the whole document be scrolled and the blobs saved as images from the inspector, at the largest screen size possible for quality.

When you have all 62 blobs you need to save the HTML page that has the text and the placement of the random numbers or renumber manually by visual inspection.

Thus it is possible to rebuild the pretend.pdf but it really is not worth the effort unless the source was deleted.

本文标签: javaHow to use Selenium to take screenshot of every page within a PDFStack Overflow