tio-boot整合playwright 将网页内容转为markdown
tio-boot官网

playwright

简介

1. 什么是 Playwright

Playwright 是一个用于自动化网页测试和浏览器操作的现代工具,由微软开发。它支持多种浏览器,包括 Chromium、Firefox 和 WebKit,并提供跨浏览器一致的 API。以下是 Playwright 的一些关键特点:

  1. 多浏览器支持:Playwright 支持 Chromium(包括 Google Chrome 和 Microsoft Edge)、Firefox 和 WebKit(包括 Safari)。这使得开发者可以在多个浏览器上进行一致的测试。
  2. 自动化测试:Playwright 提供强大的自动化测试功能,支持测试用例的编写和执行,可以用于端到端(E2E)测试,功能测试和回归测试等。
  3. 丰富的 API:Playwright 拥有一个强大而直观的 API,用于浏览器自动化、页面导航、表单填写、截图、PDF 生成等。
  4. 并行测试:Playwright 支持并行执行测试,这使得测试可以更快完成,从而提高 CI/CD 管道的效率。
  5. 无头模式和有头模式:Playwright 支持无头模式(headless)和有头模式(headful),无头模式下不会打开浏览器窗口,有头模式下则会。
  6. 跨平台:Playwright 可以在 Windows、Mac 和 Linux 上运行,并且可以在本地和 CI 环境中使用。
  7. 自动处理页面同步:Playwright 自动处理页面加载、元素可见性和其他同步问题,减少了开发者手动等待的需求。
  8. 强大的选择器:Playwright 提供多种选择器策略,包括 CSS 选择器、文本选择器、XPath 等,方便定位页面元素。
  9. 网络拦截和模拟:Playwright 允许拦截和模拟网络请求,可以用于测试不同的网络条件和 API 响应。
  10. 截图和视频录制:Playwright 支持截取网页截图和录制测试过程的视频,有助于调试和记录测试结果。

总的来说,Playwright 是一个功能强大且灵活的网页自动化工具,适用于各种测试和自动化需求。

2. Playwright 和 Selenium 的关系

Playwright 和 Selenium 都是用于浏览器自动化的工具,但它们有一些关键的区别和特点:

  • 历史背景

    • Selenium:Selenium 是一个开源的自动化工具,早于 Playwright 出现,已经有很多年历史。它支持多种浏览器(Chrome、Firefox、Safari、Edge 等)和编程语言(如 Java、Python、C#、Ruby 等)。Selenium 的设计理念是在多个浏览器中提供一致的自动化 API。
    • Playwright:Playwright 是由微软开发的相对较新的自动化框架。它专注于现代 Web 应用的测试,支持 Chromium、Firefox 和 WebKit。Playwright 的设计目标是提供更高效、稳定和一致的自动化体验。
  • API 和功能

    • Selenium:Selenium 提供了一个广泛的 API,但在处理一些现代 Web 应用中的复杂交互时,可能会遇到一些问题。它的 API 在不同浏览器间的一致性方面有时会出现差异。
    • Playwright:Playwright 提供了更现代化的 API,支持自动处理页面同步、网络拦截、模拟等功能。它的 API 一致性较好,可以在多个浏览器中实现相似的行为。
  • 性能和稳定性

    • Selenium:由于 Selenium 的历史悠久,它在性能和稳定性方面可能会遇到一些挑战,特别是在复杂的 Web 应用场景中。
    • Playwright:Playwright 在性能和稳定性方面有优势,尤其是在处理现代 Web 应用和复杂用户交互时。它的并行测试和自动同步功能可以显著提高测试效率。

3. Playwright 是否是客户端服务器模式?

Playwright 本身不是客户端-服务器模式的工具,而是一个客户端库。它通过客户端库与浏览器进行交互,这些浏览器实例可以运行在本地机器或远程服务器上。以下是 Playwright 的架构和工作方式:

  • 客户端库:Playwright 提供了一个客户端库,开发者通过这个库编写测试脚本和自动化任务。这个库可以与 Chromium、Firefox 和 WebKit 浏览器进行通信。
  • 浏览器实例:浏览器实例可以在本地机器上运行,也可以在远程服务器上运行(通过远程浏览器调试协议)。Playwright 支持这种灵活的配置,但它自身并不提供服务器功能。
  • Playwright Server:在某些情况下,Playwright 可以与一个独立的 Playwright Server 进行交互,这个服务器负责提供浏览器实例并处理自动化请求。但这种模式更多的是用于集成测试环境,而不是 Playwright 的主要设计模式。

总结来说,Playwright 主要是一个客户端库,用于与浏览器进行自动化交互,不是传统意义上的客户端-服务器模式工具。

4. Playwright 对 java 的支持

Playwright 支持 Java。Playwright 提供了官方的 Java 客户端库,允许开发者使用 Java 编写测试脚本和进行浏览器自动化操作。Playwright 的 Java 客户端库与其他语言的客户端库一样,提供了丰富的功能,用于处理浏览器交互、页面操作和自动化测试等任务。

如何使用 Playwright 的 Java 客户端库

  1. 安装 Playwright Java 客户端库
    使用 Maven 或 Gradle 来添加 Playwright 的依赖。

    Maven 配置示例:

    <dependency>
      <groupId>com.microsoft.playwright</groupId>
      <artifactId>playwright</artifactId>
      <version>1.27.0</version> <!-- 请检查最新版本 -->
    </dependency>

    playwright 的客户端 driver-bundle-1.27.0.jar 有 117M

    Gradle 配置示例:

    dependencies {
      implementation 'com.microsoft.playwright:playwright:1.27.0' // 请检查最新版本
    }
  2. 编写 Playwright 测试脚本
    使用 Java 编写测试脚本的基本示例如下:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.BrowserType;
import com.microsoft.playwright.BrowserType.LaunchOptions;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Page.ScreenshotOptions;
import com.microsoft.playwright.Playwright;

public class PlaywrightExample {
  public static void main(String[] args) {
    String url = "https://www.sjsu.edu/classes/calendar/2024-2025.php";

    // 创建 Playwright 实例
    try (Playwright playwright = Playwright.create()) {
      // 启动 Chromium 浏览器
      LaunchOptions launchOptions = new BrowserType.LaunchOptions().setHeadless(true);
      Browser browser = playwright.chromium().launch(launchOptions);
      // 创建新页面
      BrowserContext context = browser.newContext();
      Page page = context.newPage();
      // 导航到网页
      page.navigate(url);
      // 截取页面截图
      ScreenshotOptions screenshotOptions = new Page.ScreenshotOptions().setPath(Paths.get("example.png"));
      page.screenshot(screenshotOptions);
      //获取内容,写入数据
      String content = page.content();
      try {
        Files.write(Paths.get("remote_page.html"), content.getBytes());
      } catch (IOException e) {
        e.printStackTrace();
      }
      // 关闭浏览器
      browser.close();
    }
  }
}

第一次启动会自动下载

  • FFMPEG playwright build v1007 1.4 Mb
  • Firefox 105.0.1 (playwright build v1357) 77 Mb
  • Webkit 16.0 (playwright build v1724) 58Mb
  • Chromium 107.0.5304.18 (playwright build v1028).109.2 Mb
  1. 运行测试
    确保您的项目配置正确,并且 Playwright 的相关依赖已经被下载。运行您的 Java 应用程序以执行 Playwright 脚本。

远程连接

Playwright 支持服务器模式,启动 Playwright 服务器后可以使用 Java 进行远程浏览器连接。

我们可以将 Playwright 配置为与远程浏览器进行交互,这对于在分布式测试环境或云服务上运行测试非常有用。以下是一些关于如何设置 Playwright Java 客户端库以支持远程连接的基本步骤:

1. 安装 chromium

1). 更新包管理器:

sudo apt update

2). 安装 Chromium:

sudo apt install chromium-browser -y

2. 启动远程浏览器

通过命令行启动浏览器并指定远程调试端口。

chromium --no-sandbox --headless --disable-gpu --remote-debugging-port=9222

使用 chromium --remote-debugging-port=9222 启动 Chromium 时,它会启动一个 Chromium 实例并在指定端口上开启一个远程调试服务器。例如,启动 Chromium 并监听端口 9222.这个服务器允许通过 WebSocket 连接进行远程控制。

  • --no-sandbox 使用 root 命令直接运行
  • --headless:开启无头模式 在纯命令行环境下启动 Chromium 并且没有 X11 窗口支持(例如在服务器或无头模式下),你可以使用 无头模式 来启动 Chromium。无头模式允许 Chromium 在没有图形界面的情况下运行。
    启动成功后监听的窗口
DevTools listening on ws://127.0.0.1:9222/devtools/browser/86a5e2f5-2d49-4639-bcf2-d6be0cf0c59d

3. 配置 Playwright Java 客户端库连接到远程浏览器

远程调试服务器相当于一个服务端,接受来自客户端的调试命令。客户端则是你的 Playwright Java 应用程序,它通过 WebSocket 连接到这个远程调试服务器并发送命令来控制浏览器。

在 Java 代码中,使用 Playwright Java 客户端库连接到远程浏览器。以下是一个简单的示例代码,展示如何连接到远程浏览器并进行操作:

package com.litongjava.playwright.example;

import java.nio.file.Paths;

import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.BrowserType;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;

public class RemotePlaywrightExample {
  public static void main(String[] args) {
    // 创建 Playwright 实例
    try (Playwright playwright = Playwright.create()) {
      // 连接到远程浏览器实例
      BrowserType browserType = playwright.chromium();
      Browser browser = browserType.connect("ws://localhost:9222");

      // 创建新的浏览器上下文和页面
      BrowserContext context = browser.newContext();
      Page page = context.newPage();

      // 导航到网页
      page.navigate("https://example.com");

      // 截取页面截图
      page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("remote_example.png")));

      // 关闭浏览器
      browser.close();
    }
  }
}

Flexmark (Markdown Processor)

1. 简介

Flexmark 是一个功能强大的 Java Markdown 处理库,支持将 HTML 转换为 Markdown。它提供灵活的 API,可以从 HTML 中提取内容并将其转换为符合 Markdown 语法的文本格式。Flexmark 提供了多种扩展和选项,使得在各种 Markdown 转换场景中都能得心应手。

2. 添加依赖

在你的 pom.xml 文件中添加以下 Maven 依赖,确保引入 Flexmark 库:

<dependency>
  <groupId>com.vladsch.flexmark</groupId>
  <artifactId>flexmark-all</artifactId>
  <version>0.62.2</version>
</dependency>

3. 将 HTML 转换为 Markdown

以下是一个使用 Flexmark 将 HTML 转换为 Markdown 的示例:

import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter;

public class HtmlToMarkdown {
    public static void main(String[] args) {
        // 要转换的 HTML 字符串
        String html = "<h1>Hello World</h1><p>This is a paragraph.</p>";

        // 创建 HTML 到 Markdown 转换器实例
        FlexmarkHtmlConverter converter = FlexmarkHtmlConverter.builder().build();

        // 进行转换
        String markdown = converter.convert(html);

        // 输出转换后的 Markdown 内容
        System.out.println(markdown);
    }
}

4. 输出结果

运行上述代码后,输出的 Markdown 内容如下:

# Hello World

This is a paragraph.

通过 Flexmark,你可以轻松实现 HTML 到 Markdown 的转换,且转换后的内容格式整洁、易读,适用于博客、文档生成等多个场景。

Playwright-Server 整合方案

1. 简介

在使用 Playwright 进行网页数据抓取时,每次启动 Playwright 都会带来较大的性能开销。为解决这个问题,可以通过在服务启动时初始化 Playwright,并在服务关闭时正确释放资源,从而提升性能。本文介绍如何使用 TioBoot 整合 Playwright,实现高效的网页数据获取服务。
同时 Playwright 的依赖非常多,我们将 Playwright 封装成一个 web 服务,对外提供 Api

2. Playwright 实例管理

为了避免每次请求都重新启动浏览器,Playwright 实例可以在服务启动时初始化,并在需要时使用。

package com.litongjava.playwright.instance;

import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.BrowserType;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;

public enum PlaywrightBrowser {
  INSTANCE;

  // 创建 Playwright 实例
  public static Playwright playwright = Playwright.create();
  public static Browser browser;

  static {
    // 启动 Chromium 浏览器
    BrowserType.LaunchOptions launchOptions = new BrowserType.LaunchOptions().setHeadless(true); // 无头模式
    browser = playwright.chromium().launch(launchOptions);
  }

  public static Browser browser() {
    return browser;
  }

  public static void close() {
    browser.close();
    playwright.close();
  }

  public static String getContent(String url) {
    BrowserContext context = browser.newContext();
    Page page = context.newPage();
    page.navigate(url);
    String content = page.content();
    page.close();
    return content;
  }
}

3. Playwright 配置类

在服务启动时初始化 Playwright,在服务关闭时自动释放资源,保证高效的资源管理。

package com.litongjava.playwright.config;

import com.litongjava.jfinal.aop.annotation.AConfiguration;
import com.litongjava.jfinal.aop.annotation.AInitialization;
import com.litongjava.playwright.instance.PlaywrightBrowser;
import com.litongjava.tio.boot.server.TioBootServer;

@AConfiguration
public class PlaywrightConfig {

  @AInitialization
  public void config() {
    PlaywrightBrowser.browser(); // 启动浏览器实例

    // 服务关闭时释放资源
    TioBootServer.me().addDestroyMethod(() -> {
      PlaywrightBrowser.close();
    });
  }
}
  • 说明

    • 使用 @AConfiguration@AInitialization 注解,在服务启动时自动创建 Browser 实例。
    • 将 Playwright 和 Chromium 浏览器的启动设置为无头模式,适合服务器环境。
    • 在服务销毁时,利用 TioBootServeraddDestroyMethod 方法,确保浏览器和 Playwright 实例被正确关闭,避免资源泄漏。

4. Playwright 控制器

通过控制器实现网页内容获取和 Markdown 转换功能。

package com.litongjava.playwright.controller;

import com.litongjava.playwright.instance.PlaywrightBrowser;
import com.litongjava.tio.boot.http.TioRequestContext;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.server.annotation.RequestPath;
import com.litongjava.tio.http.server.util.Resps;

import lombok.extern.slf4j.Slf4j;

@RequestPath("/playwright")
@Slf4j
public class PlaywrightController {

  @RequestPath()
  public HttpResponse index(String url) {
    log.info("访问的 URL: {}", url);

    String content = PlaywrightBrowser.getContent(url);

    // 返回网页内容
    return Resps.html(TioRequestContext.getResponse(), content);
  }
}
package com.litongjava.playwright.controller;

import com.litongjava.playwright.instance.PlaywrightBrowser;
import com.litongjava.tio.boot.http.TioRequestContext;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.server.annotation.RequestPath;
import com.litongjava.tio.http.server.util.Resps;
import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter;

import lombok.extern.slf4j.Slf4j;

@RequestPath("/markdown")
@Slf4j
public class MarkdownController {
  @RequestPath()
  public HttpResponse markdown(String url) {
    log.info("访问的 URL: {}", url);

    String html = PlaywrightBrowser.getContent(url);

    // 创建转换器实例
    FlexmarkHtmlConverter converter = FlexmarkHtmlConverter.builder().build();

    // 将 HTML 转换为 Markdown
    String markdown = converter.convert(html);

    // 返回网页内容
    return Resps.html(TioRequestContext.getResponse(), markdown);
  }
}

5. 测试

访问下面的地址进行测试

http://localhost/playwright?url=https://www.sjsu.edu/registrar/calendar/fall-2024.php
http://localhost/markdown?url=https://www.sjsu.edu/registrar/calendar/fall-2024.php

6. 构建 Docker 镜像

为了简化部署,使用 Docker 容器化 Playwright 服务。以下是 Dockerfile 的配置:

# 第一阶段:构建
FROM litongjava/maven:3.8.8-jdk8u391 AS builder

WORKDIR /src
COPY pom.xml /src/
COPY src /src/src

RUN mvn package -DskipTests -Pproduction

# 第二阶段:运行
FROM litongjava/jdk:8u391-stable-slim

WORKDIR /app
COPY --from=builder /src/target/playwright-server-1.0.0.jar /app/

RUN apt update && apt install chromium -y && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
RUN java -jar /app/playwright-server-1.0.0.jar --download

CMD ["java", "-Xmx900m","-Xms512m","-jar", "playwright-server-1.0.0.jar"]

使用以下命令构建 Docker 镜像:

docker build -t litongjava/playwright-server:1.0.0 .

7. 总结

本文介绍了如何将 Playwright 整合到 TioBoot 中,并通过 Docker 实现高效部署。通过在服务启动时加载 Playwright 实例并在关闭时释放资源,提升了服务的响应性能。此方法特别适合需要频繁进行网页抓取或自动化测试的场景。

这样封装的服务可以有效减少启动开销,适合高并发、低延时的应用场景。


李通
215 声望0 粉丝