#web-driver #自动化 #geckodriver #chromedriver #网页 #phantomjs

fantoccini

通过WebDriver以编程方式与网页交互的高级API

70个版本

0.21.1 2024年8月3日
0.21.0 2024年7月14日
0.20.0 2024年7月14日
0.20.0-rc.72023年9月16日
0.7.1 2017年7月9日

#9 in HTTP客户端

Download history 27195/week @ 2024-05-03 22821/week @ 2024-05-10 31094/week @ 2024-05-17 30599/week @ 2024-05-24 34269/week @ 2024-05-31 24131/week @ 2024-06-07 23394/week @ 2024-06-14 30833/week @ 2024-06-21 23677/week @ 2024-06-28 22455/week @ 2024-07-05 34598/week @ 2024-07-12 28254/week @ 2024-07-19 29318/week @ 2024-07-26 24581/week @ 2024-08-02 21630/week @ 2024-08-09 20704/week @ 2024-08-16

102,222 每月下载量
用于 46 个Crate (32 直接)

MIT/Apache

205KB
3.5K SLoC

fantoccini

Crates.io Documentation codecov Gitter chat

通过WebDriver以编程方式与网页交互的高级API。

此crate使用WebDriver协议通过相对高级的操作(如“点击此元素”,“提交此表单”)来驱动符合(可能是无头)浏览器。

大多数交互都是通过使用CSS选择器来驱动的。由于大多数WebDriver兼容的浏览器都比较新,CSS标准的更高级的表达形式也得到支持,提供了相当强大操作符

首先调用Client::form来管理表单,然后使用Form上的方法来操作表单字段,最后提交表单。

为了对页面进行低级访问,可以使用Client::source来获取完整的页面HTML源代码,以及使用Client::raw_client_for来构建特定URL的原始HTTP请求。

示例

以下示例都假设您有一个在端口4444上运行的WebDriver兼容进程。一种快速的方法是在命令行中运行geckodriver

让我们从在维基百科上点击开始

use fantoccini::{ClientBuilder, Locator};

// let's set up the sequence of steps we want the browser to take
#[tokio::main]
async fn main() -> Result<(), fantoccini::error::CmdError> {
    let c = ClientBuilder::native().connect("http://localhost:4444").await.expect("failed to connect to WebDriver");

    // first, go to the Wikipedia page for Foobar
    c.goto("https://en.wikipedia.org/wiki/Foobar").await?;
    let url = c.current_url().await?;
    assert_eq!(url.as_ref(), "https://en.wikipedia.org/wiki/Foobar");

    // click "Foo (disambiguation)"
    c.find(Locator::Css(".mw-disambig")).await?.click().await?;

    // click "Foo Lake"
    c.find(Locator::LinkText("Foo Lake")).await?.click().await?;

    let url = c.current_url().await?;
    assert_eq!(url.as_ref(), "https://en.wikipedia.org/wiki/Foo_Lake");

    c.close().await
}

我们最初是如何到达Foobar页面的?我们进行了搜索!让我们让程序为我们做这件事

// -- snip wrapper code --
// go to the Wikipedia frontpage this time
c.goto("https://www.wikipedia.org/").await?;
// find the search form, fill it out, and submit it
let f = c.form(Locator::Css("#search-form")).await?;
f.set_by_name("search", "foobar").await?
 .submit().await?;

// we should now have ended up in the right place
let url = c.current_url().await?;
assert_eq!(url.as_ref(), "https://en.wikipedia.org/wiki/Foobar");

// -- snip wrapper code --

如果我们想下载一个原始文件呢?Fantoccini可以帮您解决这个问题

// -- snip wrapper code --
// go back to the frontpage
c.goto("https://www.wikipedia.org/").await?;
// find the source for the Wikipedia globe
let img = c.find(Locator::Css("img.central-featured-logo")).await?;
let src = img.attr("src").await?.expect("image should have a src");
// now build a raw HTTP client request (which also has all current cookies)
let raw = img.client().raw_client_for(http::Method::GET, &src).await?;

// we then read out the image bytes
use futures_util::TryStreamExt;
let pixels = raw
    .into_body()
    .try_fold(Vec::new(), |mut data, chunk| async move {
        data.extend_from_slice(&chunk);
        Ok(data)
    })
    .await
    .map_err(fantoccini::error::CmdError::from)?;
// and voilà, we now have the bytes for the Wikipedia logo!
assert!(pixels.len() > 0);
println!("Wikipedia logo is {}b", pixels.len());

// -- snip wrapper code --

有关更多示例,请查看examples/目录。

为fantoccini做出贡献

以下信息仅适用于有兴趣为该项目做出贡献的开发者。如果您只想用它来自动化Web浏览器,您可以跳过此部分。

如何运行测试

测试假设您已经在系统中运行了chromedrivergeckodriver。您可以通过上面的链接下载它们。然后在终端的单独标签页中运行它们。它们会一直运行,直到使用Ctrl+C终止或终端会话关闭。

然后从该项目目录运行cargo test

依赖项

~9–22MB
~361K SLoC