使用scraper crate爬取网站价格时解析出0₽的问题求助
解决网页动态价格爬取问题
问题原因
目标网站的价格数据是通过JavaScript动态渲染的。直接用reqwest获取的是服务器返回的初始HTML,此时价格字段还未被JS填充,所以显示为0 ₽;而浏览器会自动执行页面中的JS,从后端接口拉取真实价格并渲染到页面上,所以你能看到正常价格。
解决方案
方案1:使用Headless浏览器模拟渲染(适配复杂渲染场景)
通过调用Headless浏览器(如Chrome)执行页面JS,获取渲染后的完整HTML。可以用Rust的thirtyfour库(Selenium WebDriver绑定)实现:
首先在Cargo.toml中添加依赖:
[dependencies] thirtyfour = "0.32" tokio = { version = "1.0", features = ["full"] } scraper = "0.18"
然后编写执行代码:
use thirtyfour::prelude::*; use scraper::{Html, Selector}; #[tokio::main] async fn main() -> WebDriverResult<()> { // 启动ChromeDriver(需提前安装ChromeDriver并配置到系统PATH) let caps = DesiredCapabilities::chrome(); let driver = WebDriver::new("http://localhost:9515", caps).await?; // 访问目标页面 driver.get("https://gosmoke.ru/zhidkosti").await?; // 等待价格元素加载完成(可根据页面加载速度调整等待逻辑) driver.wait().until(ElementLocated(By::Css("div.price>span"))).await?; // 获取渲染后的页面源码 let html = driver.page_source().await?; let document = Html::parse_document(&html); // 解析商品名称与价格 let name_selector = Selector::parse("div.caption-title>a").unwrap(); let price_selector = Selector::parse("div.price>span").unwrap(); let names = document.select(&name_selector).map(|e| e.inner_html()); let prices = document.select(&price_selector).map(|e| e.inner_html().trim().to_string()); // 对应打印商品与价格 for (name, price) in names.zip(prices) { println!("{}: {}", name, price); } // 关闭浏览器 driver.quit().await?; Ok(()) }
方案2:直接调用后端API(更高效)
打开浏览器开发者工具(F12),切换到「网络」标签页,刷新页面后筛选XHR/Fetch类型请求,找到网站加载价格数据的后端API接口。直接请求该接口获取结构化数据,无需解析HTML。
示例代码(假设找到的API接口为https://gosmoke.ru/api/products,需根据实际抓包结果调整):
use reqwest::Error; use serde::Deserialize; #[derive(Deserialize, Debug)] struct Product { title: String, price: String, } #[tokio::main] async fn main() -> Result<(), Error> { let client = reqwest::Client::new(); // 可能需要添加User-Agent等请求头模拟浏览器 let response = client.get("https://gosmoke.ru/api/products") .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36") .send() .await? .json::<Vec<Product>>() .await?; for product in response { println!("{}: {}", product.title, product.price); } Ok(()) }
内容的提问来源于stack exchange,提问作者rustscr1pt
相关产品推荐
相关产品推荐

