SDKs

Rust

Thunderbit Open API のための Rust イディオムなパターン

reqwest + serde + tokio を使います。デフォルトで非同期です。並列展開には futures::stream::iter を組み合わせましょう。

Cargo.toml

[dependencies]
reqwest = { version = "0.12", features = ["json"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1", features = ["full"] }

Configure

use reqwest::Client;
use serde_json::json;

const API: &str = "https://openapi.thunderbit.com/openapi/v1";

fn client() -> Client {
    Client::builder()
        .timeout(std::time::Duration::from_secs(60))
        .build()
        .unwrap()
}

fn auth() -> String {
    format!("Bearer {}", std::env::var("THUNDERBIT_API_KEY").unwrap())
}

ページを Distill する

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let res: serde_json::Value = client()
        .post(format!("{API}/distill"))
        .header("Authorization", auth())
        .json(&json!({ "url": "https://thunderbit.com/playground" }))
        .send()
        .await?
        .error_for_status()?
        .json()
        .await?;
    println!("{}", res["data"]["markdown"]);
    Ok(())
}

構造化データを Extract する

let res: serde_json::Value = client()
    .post(format!("{API}/extract"))
    .header("Authorization", auth())
    .json(&json!({
        "url": "https://example.com/product/iphone-15-pro",
        "schema": {
            "type": "object",
            "properties": {
                "name":  { "type": "string" },
                "price": { "type": "number" }
            },
            "required": ["name", "price"]
        }
    }))
    .send().await?.error_for_status()?.json().await?;

Batch を並列展開する

(Batch エンドポイントではなく)単発の distill を高並列で叩きたい場合は、上限付きの JoinSet を使います。

use tokio::task::JoinSet;

let mut set = JoinSet::new();
for url in urls {
    let c = client();
    set.spawn(async move {
        c.post(format!("{API}/distill"))
            .header("Authorization", auth())
            .json(&json!({ "url": url }))
            .send().await?.error_for_status()?
            .json::<serde_json::Value>().await
    });
}
while let Some(res) = set.join_next().await { /* … */ }

10 件以上の URL を扱う場合は、並列展開より /batch/distill のほうが望ましいです —— Batch Job Lifecycle を参照。

公式 Rust SDK は開発中です —— もう少しお待ちください。