aliexpress_scraper/
lib.rs

1mod structs;
2
3/// Fetches product details from aliexpress.
4///
5/// # Example
6///
7/// ```
8/// let product_details: Product = get_product_details("1005005115304061").await.unwrap();
9/// ```
10///
11/// You can get the product id from the url: https://aliexpress.com/item/[ID].html
12pub async fn get_product_details(product_id: &str) -> Result<structs::Product, &str> {
13    let page = match get_aliexpress_html(product_id).await {
14        Err(e) => return Err(e),
15        Ok(page) => page,
16    };
17    let run_params_string = match filter_run_params(page) {
18        Ok(params) => params,
19        Err(_) => return Err("Failed to parse product page"),
20    };
21
22    println!("{}", run_params_string.contains("actionModule"));
23
24    ::std::fs::write("output.json", &run_params_string).unwrap();
25
26    let run_params: structs::Product = serde_json::from_str(&run_params_string).unwrap();
27
28    return Ok(run_params);
29}
30
31fn filter_run_params(page: String) -> Result<String, ()> {
32    const END_PADDING: usize = 11;
33    let mut res = page.as_str();
34
35    res = res.split("window.runParams = ").collect::<Vec<&str>>()[1];
36    res = res.split("};").collect::<Vec<&str>>()[0];
37    let temp_res = res.to_owned() + "}";
38    res = temp_res.as_str();
39    let res_filter = res
40        .lines()
41        .filter(|line| {
42            !line.contains("csrfToken")
43                && !line.contains("abVersion")
44                && !line.contains("abtestMap")
45        })
46        .collect::<Vec<&str>>();
47
48    let joined_res_filter = res_filter.join("\n");
49    res = joined_res_filter.as_str();
50    let temp_res = res.replace("data:", "");
51    res = temp_res.as_str();
52
53    res = &res[1..res.len() - END_PADDING];
54
55    return Ok(res.to_owned());
56}
57
58async fn get_aliexpress_html(product_id: &str) -> Result<String, &str> {
59    let res_result =
60        reqwest::get(format!("https://www.aliexpress.com/item/{product_id}.html")).await;
61
62    if let Err(_) = res_result {
63        return Err("Request error");
64    } else if let Ok(res) = res_result {
65        if res.status() != 200 {
66            return Err("Status code error");
67        }
68
69        let text_result = res.text().await;
70
71        if let Err(_) = text_result {
72            return Err("Failed to fetch product page");
73        } else if let Ok(text) = text_result {
74            if text.contains("Sorry, we can't find that page") {
75                return Err("Product page not found");
76            }
77            if text.contains("punish-page") {
78                return Err("You've rate limited by Aliexpress.");
79            }
80
81            return Ok(text);
82        }
83    }
84
85    return Ok(String::new());
86}