playwright update
This commit is contained in:
@@ -45,7 +45,7 @@ aes-gcm = "0.10"
|
||||
cbc = { version = "0.1", features = ["alloc"] }
|
||||
hex = "0.4"
|
||||
chromiumoxide = { version = "0.7", features = ["tokio-runtime"] }
|
||||
playwright = "0.0.20"
|
||||
playwright-rs = "0.7"
|
||||
|
||||
[lints.rust]
|
||||
warnings = "warn"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use playwright::Playwright;
|
||||
use playwright::api::Page;
|
||||
use playwright_rs::{LaunchOptions, Page, Playwright};
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
use tokio::time::{sleep, timeout};
|
||||
@@ -52,24 +51,29 @@ pub async fn wait_for_attribute(
|
||||
attribute: &str,
|
||||
wait_timeout: Duration,
|
||||
) -> Option<String> {
|
||||
// _pw must be kept alive — dropping it kills the driver process.
|
||||
let (_pw, page) = open_page(url).await?;
|
||||
// _browser is kept alive (Arc inside Playwright) — the page borrows from it.
|
||||
// The Page holds its own server reference, so dropping our local Playwright
|
||||
// handle does not shut the driver down.
|
||||
let (page, _browser, _playwright) = open_page(url).await?;
|
||||
|
||||
let xpath_js = serde_json::to_string(xpath).unwrap_or_default();
|
||||
let attr_js = serde_json::to_string(attribute).unwrap_or_default();
|
||||
// playwright-rs's evaluate_value takes a single JS expression, so wrap the
|
||||
// multi-statement lookup in an IIFE. The return value is auto-converted to
|
||||
// a String by the Playwright protocol layer.
|
||||
let js = format!(
|
||||
r#"() => {{
|
||||
r#"(() => {{
|
||||
var r = document.evaluate({xpath_js}, document, null,
|
||||
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
|
||||
var el = r.singleNodeValue;
|
||||
if (!el) return '';
|
||||
return el.getAttribute({attr_js}) || el[{attr_js}] || '';
|
||||
}}"#
|
||||
}})()"#
|
||||
);
|
||||
|
||||
let result = timeout(wait_timeout, async {
|
||||
loop {
|
||||
match page.evaluate::<(), String>(&js, ()).await {
|
||||
match page.evaluate_value(&js).await {
|
||||
Ok(s) if !s.is_empty() => return Some(s),
|
||||
Ok(_) => {}
|
||||
Err(e) => eprintln!("[playwright] evaluate error: {e}"),
|
||||
@@ -86,43 +90,48 @@ pub async fn wait_for_attribute(
|
||||
|
||||
// ── internals ─────────────────────────────────────────────────────────────────
|
||||
|
||||
async fn open_page(url: &str) -> Option<(Playwright, Page)> {
|
||||
let pw = Playwright::initialize()
|
||||
/// Launches Playwright (Node server + bundled Chromium), opens a page on
|
||||
/// `url`, and returns a handle. Caller is responsible for keeping the
|
||||
/// returned `Playwright` and `Browser` handles alive while the page is in
|
||||
/// use — dropping the browser closes the page and driver.
|
||||
async fn open_page(
|
||||
url: &str,
|
||||
) -> Option<(Page, playwright_rs::Browser, Playwright)> {
|
||||
let playwright = Playwright::launch()
|
||||
.await
|
||||
.map_err(|e| eprintln!("[playwright] init error: {e}"))
|
||||
.ok()?;
|
||||
|
||||
let args: Vec<String> = CHROME_ARGS.iter().map(|s| s.to_string()).collect();
|
||||
|
||||
let browser = pw
|
||||
.chromium()
|
||||
.launcher()
|
||||
.executable(Path::new("/usr/bin/google-chrome"))
|
||||
let options = LaunchOptions::new()
|
||||
.headless(true)
|
||||
.args(&args)
|
||||
.launch()
|
||||
.chromium_sandbox(false)
|
||||
.args(args)
|
||||
.executable_path(
|
||||
Path::new("/usr/bin/google-chrome")
|
||||
.to_str()
|
||||
.unwrap_or("/usr/bin/google-chrome")
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
let browser = playwright
|
||||
.chromium()
|
||||
.launch_with_options(options)
|
||||
.await
|
||||
.map_err(|e| eprintln!("[playwright] launch error: {e}"))
|
||||
.ok()?;
|
||||
|
||||
let context = browser
|
||||
.context_builder()
|
||||
.build()
|
||||
.await
|
||||
.map_err(|e| eprintln!("[playwright] context error: {e}"))
|
||||
.ok()?;
|
||||
|
||||
let page = context
|
||||
let page = browser
|
||||
.new_page()
|
||||
.await
|
||||
.map_err(|e| eprintln!("[playwright] new_page error: {e}"))
|
||||
.ok()?;
|
||||
|
||||
page.goto_builder(url)
|
||||
.goto()
|
||||
page.goto(url, None)
|
||||
.await
|
||||
.map_err(|e| eprintln!("[playwright] goto error: {e}"))
|
||||
.ok()?;
|
||||
|
||||
Some((pw, page))
|
||||
Some((page, browser, playwright))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user