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

如何用Java Streams优化Ebay自动化Selenium代码及FilterCarrier方法?

eBay自动化脚本优化:Java Streams应用与FilterCarrier方法改进

我是编程新手,编写了一段可运行的Ebay网站自动化脚本,但代码较为杂乱。现咨询如何使用Java Streams优化该代码,同时想了解是否有更简便的方式编写FilterCarrier方法,即是否存在更优的迭代实现方式。

以下是我的原代码:

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import javax.imageio.ImageIO;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.Point;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.io.FileHandler;

public class EbayTestCase {

    public static void main(String[] args) throws InterruptedException, IOException {
        // TODO Auto-generated method stub
        System.setProperty("webdriver.chrome.driver",
                "C:\\Users\\Mehdee\\Documents\\Eclipse projects\\Selenium\\ChromeDriver\\chromedriver.exe");
        WebDriver driver = new ChromeDriver();
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
        // WebDriverWait w = new WebDriverWait(driver, Duration.ofSeconds(30));
        driver.get("https://www.ebay.com/");
        String[] carrFilter = { "Verizon", "T-Mobile", "Unlocked", "1&1" };
        driver.findElement(By.id("gh-ac")).sendKeys("iPhone 14");
        driver.findElement(By.id("gh-btn")).click();
        System.out.println(ResultCount(driver) + " For iPhone 14");
        Thread.sleep(1500);
        driver.findElement(By.cssSelector("input[aria-label='Apple iPhone 14 Pro Max']")).click();
        System.out.println(ResultCount(driver) + " For Apple iPhone 14 Pro Max");

        FilterCarrier(driver, carrFilter);

        ElementScreenshot(driver);
        driver.quit();

    }

    public static void ElementScreenshot(WebDriver driver) throws IOException {
        WebElement ele = driver.findElement(
                By.xpath("//body/div[5]/div[4]/div[2]/div[1]/div[2]/ul[1]/li[2]/div[1]/div[1]/div[1]/a[1]/div[1]"));
        File SC = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
        Point location = ele.getLocation();
        int height = ele.getSize().getHeight();
        int width = ele.getSize().getWidth();
        BufferedImage img = ImageIO.read(SC);
        BufferedImage cropped = img.getSubimage(location.getX(), location.getY(), width, height);
        ImageIO.write(cropped, "png", SC);
        File fis = new File("C:\\Users\\Mehdee\\Documents\\SeleniumScreenshots\\screenshot.png");
        FileHandler.copy(SC, fis);
        System.out.println("Screenshot has been successfully stored in C://Documents/SeleniumScreenshots directory");
    }

    public static String ResultCount(WebDriver driver) {
        String[] t = driver.findElement(By.cssSelector(".srp-controls__count-heading")).getText().split(" ");
        String resultCount = t[0] + " Results Found";
        return resultCount;
    }

    public static void FilterCarrier(WebDriver driver, String[] carrFilter) {
        List<WebElement> options = driver
                .findElements(By.xpath("//div[@id='x-refine__group_1__1']/ul/li/div/a/div/span/input"));
        int b = 0;
        for (int i = 0; i < options.size(); i++) {

            List<String> carrNames = Arrays.asList(carrFilter);
            WebElement option = options.get(i);
            String label = option.getAttribute("aria-label");
            if (carrNames.contains(label)) {
                b++;
                options.get(i).click();
                System.out.println(ResultCount(driver) + " for: " + label);
                options = driver.findElements(By.xpath("//div[@id='x-refine__group_1__1']/ul/li/div/a/div/span/input"));
                if (b == 4) {
                    break;
                }

            }
        }
    }
}

优化方案

一、核心问题梳理

原代码存在几个可优化的点:

  1. FilterCarrier方法中每次循环都创建List<String> carrNames,重复操作浪费性能;
  2. 硬编码的路径、选择器不易维护;
  3. 字符串处理、元素遍历可以通过Java Streams简化,提升可读性;
  4. 手动计数的迭代逻辑冗余。

二、具体优化实现

1. 提取常量,提升可维护性

把硬编码的驱动路径、截图路径、页面选择器等抽成类常量,避免重复修改:

private static final String CHROME_DRIVER_PATH = "C:\\Users\\Mehdee\\Documents\\Eclipse projects\\Selenium\\ChromeDriver\\chromedriver.exe";
private static final String SCREENSHOT_SAVE_PATH = "C:\\Users\\Mehdee\\Documents\\SeleniumScreenshots\\screenshot.png";
private static final By CARRIER_FILTER_OPTIONS = By.xpath("//div[@id='x-refine__group_1__1']/ul/li/div/a/div/span/input");
private static final By RESULT_COUNT_SELECTOR = By.cssSelector(".srp-controls__count-heading");

2. 用Java Streams优化ResultCount方法

原方法通过数组分割处理字符串,用Streams可以更严谨地提取第一个元素,避免数组越界风险:

public static String ResultCount(WebDriver driver) {
    return Arrays.stream(driver.findElement(RESULT_COUNT_SELECTOR).getText().split(" "))
            .findFirst()
            .orElse("0") + " Results Found";
}

3. 改进FilterCarrier方法(核心优化)

原方法的迭代逻辑可以用Streams结合Set优化:

  • 将carrFilter转为HashSet,提升contains查询效率(O(1) vs List的O(n));
  • 用Stream的filter筛选目标元素,处理点击后DOM更新的问题(每次获取最新元素列表,避免旧元素失效);
  • 移除已处理的运营商,避免重复点击。

优化后的FilterCarrier:

public static void FilterCarrier(WebDriver driver, String[] carrFilter) {
    Set<String> targetCarriers = new HashSet<>(Arrays.asList(carrFilter));
    int processedCount = 0;
    
    while (processedCount < carrFilter.length) {
        List<WebElement> options = driver.findElements(CARRIER_FILTER_OPTIONS);
        Optional<WebElement> targetOption = options.stream()
                .filter(elem -> targetCarriers.contains(elem.getAttribute("aria-label")))
                .findFirst();
        
        if (targetOption.isEmpty()) {
            break;
        }
        
        WebElement elem = targetOption.get();
        String label = elem.getAttribute("aria-label");
        elem.click();
        processedCount++;
        
        System.out.println(ResultCount(driver) + " for: " + label);
        targetCarriers.remove(label);
        
        // 可选:等待页面加载,避免元素失效
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

4. 简化ElementScreenshot方法

简化变量声明,用常量存储元素定位器,提升代码可读性:

private static final By TARGET_SCREENSHOT_ELEMENT = By.xpath("//body/div[5]/div[4]/div[2]/div[1]/div[2]/ul[1]/li[2]/div[1]/div[1]/div[1]/a[1]/div[1]");

public static void ElementScreenshot(WebDriver driver) throws IOException {
    WebElement ele = driver.findElement(TARGET_SCREENSHOT_ELEMENT);
    File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
    
    BufferedImage fullImg = ImageIO.read(screenshot);
    Point location = ele.getLocation();
    BufferedImage croppedImg = fullImg.getSubimage(
            location.getX(), 
            location.getY(), 
            ele.getSize().getWidth(), 
            ele.getSize().getHeight()
    );
    
    ImageIO.write(croppedImg, "png", screenshot);
    FileHandler.copy(screenshot, new File(SCREENSHOT_SAVE_PATH));
    System.out.println("截图已保存至:" + SCREENSHOT_SAVE_PATH);
}

三、完整优化后代码

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import javax.imageio.ImageIO;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.Point;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.io.FileHandler;

public class EbayTestCase {
    // 常量提取
    private static final String CHROME_DRIVER_PATH = "C:\\Users\\Mehdee\\Documents\\Eclipse projects\\Selenium\\ChromeDriver\\chromedriver.exe";
    private static final String SCREENSHOT_SAVE_PATH = "C:\\Users\\Mehdee\\Documents\\SeleniumScreenshots\\screenshot.png";
    private static final By CARRIER_FILTER_OPTIONS = By.xpath("//div[@id='x-refine__group_1__1']/ul/li/div/a/div/span/input");
    private static final By RESULT_COUNT_SELECTOR = By.cssSelector(".srp-controls__count-heading");
    private static final By TARGET_SCREENSHOT_ELEMENT = By.xpath("//body/div[5]/div[4]/div[2]/div[1]/div[2]/ul[1]/li[2]/div[1]/div[1]/div[1]/a[1]/div[1]");

    public static void main(String[] args) throws InterruptedException, IOException {
        System.setProperty("webdriver.chrome.driver", CHROME_DRIVER_PATH);
        WebDriver driver = new ChromeDriver();
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
        
        driver.get("https://www.ebay.com/");
        String[] carrFilter = { "Verizon", "T-Mobile", "Unlocked", "1&1" };
        
        // 搜索iPhone 14
        driver.findElement(By.id("gh-ac")).sendKeys("iPhone 14");
        driver.findElement(By.id("gh-btn")).click();
        System.out.println(ResultCount(driver) + " For iPhone 14");
        
        Thread.sleep(1500);
        // 筛选Pro Max型号
        driver.findElement(By.cssSelector("input[aria-label='Apple iPhone 14 Pro Max']")).click();
        System.out.println(ResultCount(driver) + " For Apple iPhone 14 Pro Max");
        
        // 筛选运营商
        FilterCarrier(driver, carrFilter);
        
        // 截图
        ElementScreenshot(driver);
        
        driver.quit();
    }

    public static void ElementScreenshot(WebDriver driver) throws IOException {
        WebElement ele = driver.findElement(TARGET_SCREENSHOT_ELEMENT);
        File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
        
        BufferedImage fullImg = ImageIO.read(screenshot);
        Point location = ele.getLocation();
        BufferedImage croppedImg = fullImg.getSubimage(
                location.getX(), 
                location.getY(), 
                ele.getSize().getWidth(), 
                ele.getSize().getHeight()
        );
        
        ImageIO.write(croppedImg, "png", screenshot);
        FileHandler.copy(screenshot, new File(SCREENSHOT_SAVE_PATH));
        System.out.println("截图已保存至:" + SCREENSHOT_SAVE_PATH);
    }

    public static String ResultCount(WebDriver driver) {
        return Arrays.stream(driver.findElement(RESULT_COUNT_SELECTOR).getText().split(" "))
                .findFirst()
                .orElse("0") + " Results Found";
    }

    public static void FilterCarrier(WebDriver driver, String[] carrFilter) {
        Set<String> targetCarriers = new HashSet<>(Arrays.asList(carrFilter));
        int processedCount = 0;
        
        while (processedCount < carrFilter.length) {
            List<WebElement> options = driver.findElements(CARRIER_FILTER_OPTIONS);
            Optional<WebElement> targetOption = options.stream()
                    .filter(elem -> targetCarriers.contains(elem.getAttribute("aria-label")))
                    .findFirst();
            
            if (targetOption.isEmpty()) {
                break;
            }
            
            WebElement elem = targetOption.get();
            String label = elem.getAttribute("aria-label");
            elem.click();
            processedCount++;
            
            System.out.println(ResultCount(driver) + " for: " + label);
            targetCarriers.remove(label);
            
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Mehdee Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 19:17:33