HTTP 客户端无法从 e-commerce 网站检索内容

HTTP client not working for retrieving content from e-commerce website

我正在尝试用 Rust 实现网页观察器。基本思路是,当在页面内容中找不到某个字符串时,我会收到通知。

基本逻辑适用于大多数情况,但对于某些 e-commerce 站点(在本例中为 argos.co.uk),它总是 return 页面显示“您没有权限访问”。

当然,同一页面在 Safari 上也能正常工作。所以我做了 Copy as cURL 这给了我以下内容:

-X 'GET' \
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15'

运行 复制的 cURL 命令按预期工作正常。所以我将这 2 个 header 添加到我的 Rust 代码中:

let cli = reqwest::Client::new();
let resp = cli
    .get(url)
    .header(USER_AGENT, r#"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15"#)
    .header(ACCEPT, r#"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"#)
    .send().await?;

我仍然看到与上面相同的“您没有权限...”页面。

将上面的代码与 httpbin.org/get 一起使用表明 Rust reqwest 确实发送了正确的 header。所以我迷失了下一个寻找的地方。我的情况可能出了什么问题?

编辑

我尝试按照下面的建议将 cURL 命令与 httpbin 一起使用,并得到了以下结果。

   "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Host": "httpbin.org",
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15",
    "X-Amzn-Trace-Id": "Root=1-62011d4b-5ea67cec2c79826d5d00e959"

我不相信 X-Amzn-Trace-Id 是由 cURL 发送的,但我非常愿意被证明是错误的。

如前所述,这很可能是防止抓取的基本 header 验证。以下对我有用:

use std::error::Error;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let cli = reqwest::Client::new();
    let resp = cli
        .get("https://www.argos.co.uk/product/<YOUR_ID>")
        .header(reqwest::header::ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
        .header(reqwest::header::ACCEPT_ENCODING, "identity")
        .header(reqwest::header::ACCEPT_LANGUAGE, "en-US,en;q=0.5")
        .header(reqwest::header::USER_AGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0")
        .send().await?;

    println!("{:?}", resp.status());
    println!("{}", resp.text().await?);

    Ok(())
}

请注意,我已将 Accept-Encodinggzip 切换为 identity。您可以(而且很可能应该)使用 gzip feature.

当然,请务必遵守有关抓取的 robots.txt 和使用条款。