chrome-devtools

IYBin 956 2019-09-19

Java Client 使用示例

maven 配置

<dependency>
  <groupId>com.github.kklisura.cdt</groupId>
  <artifactId>cdt-java-client</artifactId>
  <version>2.0.0</version>
</dependency>

java 示例

import cn.hutool.core.thread.ThreadFactoryBuilder;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.github.kklisura.cdt.launch.ChromeLauncher;
import com.github.kklisura.cdt.protocol.commands.Runtime;
import com.github.kklisura.cdt.protocol.commands.*;
import com.github.kklisura.cdt.protocol.types.network.ResourceType;
import com.github.kklisura.cdt.protocol.types.network.Response;
import com.github.kklisura.cdt.protocol.types.network.ResponseBody;
import com.github.kklisura.cdt.protocol.types.page.*;
import com.github.kklisura.cdt.protocol.types.runtime.Evaluate;
import com.github.kklisura.cdt.services.ChromeDevToolsService;
import com.github.kklisura.cdt.services.ChromeService;
import com.github.kklisura.cdt.services.config.ChromeDevToolsServiceConfiguration;
import com.github.kklisura.cdt.services.executors.EventExecutorService;
import com.github.kklisura.cdt.services.types.ChromeTab;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Base64;
import java.util.concurrent.*;


/**
 * https://github.com/kklisura/chrome-devtools-java-client
 * https://chromedevtools.github.io/devtools-protocol
 */

/**
 * <dependency>
 * <groupId>com.github.kklisura.cdt</groupId>
 * <artifactId>cdt-java-client</artifactId>
 * <version>2.0.0</version>
 * </dependency>
 */
@Slf4j
public class ChromeDevtoolsJavaClientTest {

    static int resultCount = 0;

    public static void main(String[] args) throws InterruptedException {
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
                .setNamePrefix("demo-pool-%d").build();

        //Common Thread Pool
        ExecutorService pool = new ThreadPoolExecutor(5, 200,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());


        // 创建chrome启动器
        final ChromeLauncher launcher = new ChromeLauncher();
        // 以无头(true)或常规(false)方式启动chrome
        final ChromeService chromeService = launcher.launch(true);

        // 创建空标签,即:空白
        final ChromeTab tab = chromeService.createTab();

        ChromeDevToolsServiceConfiguration chromeDevToolsServiceConfiguration = new ChromeDevToolsServiceConfiguration();
        chromeDevToolsServiceConfiguration.setEventExecutorService(new EventExecutorService() {
            @Override
            public void execute(Runnable runnable) {
                pool.execute(runnable);
            }

            @Override
            public void shutdown() {
                pool.shutdown();
            }
        });

        // 获取DevTools服务到此选项卡
        final ChromeDevToolsService devToolsService = chromeService.createDevToolsService(tab, chromeDevToolsServiceConfiguration);

        // 获取单个命令
        final Page page = devToolsService.getPage();
        final DOM dom = devToolsService.getDOM();
        final Input input = devToolsService.getInput();
        final Network network = devToolsService.getNetwork();
        final Runtime runtime = devToolsService.getRuntime();

        //阻止一些网址,加快访问速度(截图时注意不要阻隔图片或者样式)
        //network.setBlockedURLs(Arrays.asList("**/*.css", "**/*.png", "**/*.svg"));
        network.setBlockedURLs(Arrays.asList("**play.google.com**"));
        // HTTP响应可用时触发
        network.onResponseReceived(event -> {
            if (ResourceType.XHR != event.getType()) {
                return;
            }
            Response response = event.getResponse();
            String requestId = event.getRequestId();
            ResponseBody responseBody = network.getResponseBody(requestId);
            System.out.printf(
                    "[%s]request: id=>%s\t%s%s",
                    getAddCount(),
                    requestId,
                    JSON.toJSONString(responseBody),
                    System.lineSeparator());
        });
        // 加载事件被触发
        page.onLoadEventFired(
                event -> {
                    log.info("页面加载完成");
                    // 执行 javascript
                    //  Evaluate evaluation = runtime.evaluate("document.documentElement.outerHTML");
                    // System.out.println(evaluation.getResult().getValue());

                    // 截屏
                    // captureFullPageScreenshot(devToolsService, page, "screenshot.png");

                    //保存至PDF
                    // printToPdf(devToolsService);
//                    Evaluate evaluate = runtime.evaluate(String.format("document.querySelector('#source').value='%s'", "hello"));
                    // log.error(JSON.toJSONString(evaluate.getExceptionDetails()));
                    int count = 10;
                    while (count-- > 0) {
                        String key = RandomUtil.randomString(6);
                        Evaluate evaluate = runtime.evaluate(String.format("document.querySelector('#source').value='%s'", key));
                        // log.error(JSON.toJSONString(evaluate.getExceptionDetails()));

                        try {
                            Thread.sleep(1000L);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                });


        // 启用页面事件
        page.enable();
        // 启用网络事件
        network.enable();

        // 导航到指定网址
        page.navigate("https://translate.google.cn");

        // 等到devtools关闭
        devToolsService.waitUntilClosed();
        // 关闭标签
        //chromeService.closeTab(tab);
    }

    private static int getAddCount() {
        return ++resultCount;
    }

    private static void printToPdf(ChromeDevToolsService devToolsService) {
        System.out.println("Printing to PDF...");

        final String outputFilename = "test.pdf";

        Boolean landscape = false;
        Boolean displayHeaderFooter = false;
        Boolean printBackground = false;
        Double scale = 1d;
        // A4 paper format
        Double paperWidth = 8.27d;
        // A4 paper format
        Double paperHeight = 11.7d;
        Double marginTop = 0d;
        Double marginBottom = 0d;
        Double marginLeft = 0d;
        Double marginRight = 0d;
        String pageRanges = "";
        Boolean ignoreInvalidPageRanges = false;
        String headerTemplate = "";
        String footerTemplate = "";
        Boolean preferCSSPageSize = false;
        PrintToPDFTransferMode mode = PrintToPDFTransferMode.RETURN_AS_BASE_64;
        PrintToPDF printToPDF = devToolsService.getPage()
        .printToPDF(landscape, displayHeaderFooter, printBackground, scale, paperWidth, paperHeight, marginTop,
         marginBottom, marginLeft, marginRight, pageRanges, ignoreInvalidPageRanges, headerTemplate,
          footerTemplate, preferCSSPageSize, mode);
        dump(outputFilename, printToPDF);

        System.out.println("Done!");
    }

    private static void captureFullPageScreenshot(ChromeDevToolsService devToolsService, Page page, String outputFilename) {
        System.out.println("Taking screenshot...");
        final LayoutMetrics layoutMetrics = page.getLayoutMetrics();

        final double width = layoutMetrics.getContentSize().getWidth();
        final double height = layoutMetrics.getContentSize().getHeight();

        final Emulation emulation = devToolsService.getEmulation();
        emulation.setDeviceMetricsOverride(
                Double.valueOf(width).intValue(), Double.valueOf(height).intValue(), 1.0d, Boolean.FALSE);

        Viewport viewport = new Viewport();
        viewport.setScale(1d);

        // You can set offset with X, Y
        viewport.setX(0d);
        viewport.setY(0d);

        // Set a width, height of a page to take screenshot at
        viewport.setWidth(width);
        viewport.setHeight(height);
        String data = page.captureScreenshot(CaptureScreenshotFormat.PNG, 100, viewport, Boolean.TRUE);
        dump(outputFilename, data);

        System.out.println("Done!");
    }

    private static void dump(String fileName, PrintToPDF printToPDF) {
        FileOutputStream fileOutputStream = null;
        try {
            File file = new File(fileName);
            fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(Base64.getDecoder().decode(printToPDF.getData()));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.flush();
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void dump(String fileName, String data) {
        FileOutputStream fileOutputStream = null;
        try {
            File file = new File(fileName);
            fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(Base64.getDecoder().decode(data));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.flush();
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


}

参考资料:

https://github.com/kklisura/chrome-devtools-java-client

https://chromedevtools.github.io/devtools-protocol