为什么 reqwest 将二进制文件下载为文本?

bax*_*000 2 mp3 web-scraping rust

我正在尝试抓取一个自动下载 mp3 文件的页面https://dl251.filemate24.shop/?file=M3R4SUNiN3JsOHJ6WWRQNXNPUFN2cFdxRVJIOGhmSXBsY1l1d2hrdFN1QnRxNGc5M3UraGFPWkpLSzRNeEl1dVd1aGQ4VHZYVG9uZE93MlpwZFlyVWlESDhkOHh2QURmOHBvb0JJd2pjQS8zanZLMmxEUXoyeUg0Ym91SVI1NE9LQ1Zka1ZJNzN5eWh5L0wrbHpqSDZpdW1wVjJRSWlrYTRYME1PUHFOeEt3TzBISGJadVhoeDVrSXFIdk90Y29maTZYTDVWYWdoYUE3dnVOMlZrRjNlTTBNbjRuamd2VE8vQT09,但使用 get 请求并将输出放入 .txt 文件中会生成一个 28,000 行长的随机 unicode 字符文件。有什么方法可以获取实际的 mp3 文件吗?是的,我正在尝试下载一首随机的 Rammstein 歌曲作为对更大项目的测试。

我使用检查元素进行了检查,该站点所做的所有操作确实是一个以某种方式生成文件的获取请求。我很确定随机 unicode 与 LAME mp3 加密有关,但我不确定如何。有没有办法从 get 请求中获取 mp3 文件?生成所述文件的 Rust 代码:

#[tokio::main]
async fn get(url: &str,client: &reqwest::Client) -> String {
    let response = client
    .get(url).send()
    .await
    .unwrap()
    .text()
    .await
    .expect("GET failed");

    response

}
fn main() {
    let client = reqwest::Client::new();
    let url = "https://dl251.filemate24.shop/?file=M3R4SUNiN3JsOHJ6WWRQNXNPUFN2cFdxRVJIOGhmSXBsY1l1d2hrdFN1QnRxNGc5M3UraGFPWkpLSzRNeEl1dVd1aGQ4VHZYVG9uZE93MlpwZFlyVWlESDhkOHh2QURmOHBvb0JJd2pjQS8zanZLMmxEUXoyeUg0Ym91SVI1NE9LQ1Zka1ZJNzN5eWh5L0wrbHpqSDZpdW1wVjJRSWlrYTRYME1PUHFOeEt3TzBISGJadVhoeDVrSXFIdk90Y29maTZYTDVWYWdoYUE3dnVOMlZrRjNlTTBNbjRuamd2VE8vQT09";
    println!("{}",url);
    let mp3 = get(url,&client);
    let mut file = std::fs::File::create("a.txt");
    std::fs::write("a.txt",mp3);
}
Run Code Online (Sandbox Code Playgroud)

抱歉,如果这是一个愚蠢的问题;总的来说,我对 Rust 和编码还很陌生。

cdh*_*wie 6

您看到文本数据是因为您在使用响应时要求提供文本数据。.text()根据.text()文档

此方法通过 BOM 嗅探和用替换字符替换格式错误的序列来解码响应正文。

换句话说,这通过用特殊的 Unicode 字符替换不代表有效文本的任何字节来将响应修改为有效文本。这确保结果作为 Rust 有效String(根据定义,必须是 UTF-8 编码文本)。 实际上,此函数调用会损坏您想要下载的 MP3 数据。

.bytes()改为使用,并将 的返回类型更改get()Vec<u8>

附带说明一下,当没有必要时,您会使用异步(tokio)。考虑改为使用reqwest::blocking.