当前位置: 首页 > news >正文

【Tauri2】050——加载html和rust爬虫

前言

好久没更新tauri了,笔者最近闲的无聊,搞搞爬虫,比如

spiderdemo第四题-CSDN博客https://blog.csdn.net/qq_63401240/article/details/153880866上面博客里面,笔者使用DP这个工具

DrissionPage官网https://www.drissionpage.cn/笔者使用这个工具的目的

  1. 加载html
  2. 执行js

笔者突然想到,tauri好像也可以加载html,然后就有个想法,试试rust爬虫,使用tauri加载html页面,执行加密函数,获取加密参数,发送请求。

感觉没问题。

那么,就以spiderdemo的第21题为例子。

T21-摘要算法https://www.spiderdemo.cn/authentication/hash_challenge/?challenge_type=hash_challenge编写rust爬虫,顺便作为tauri的教程。

正文

建立一个加载html的tauri项目

直接给出文件及其内容


cargo.toml


[package]
name = "html-t"
edition = "2024"[build-dependencies]
tauri-build = { version = "2", features = [] }[dependencies]
tauri = "2"

src/main.rs


#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]#[tauri::command]
fn greet(name: &str) -> String {format!("Hello {name}, You have been greeted from Rust!")
}fn main() {tauri::Builder::default().invoke_handler(tauri::generate_handler![greet]).run(tauri::generate_context!()).expect("error while running tauri application");
}

tauri.config.json


{"$schema": "https://schema.tauri.app/config/2","productName": "start","version": "0.1.0","identifier": "com.start.app","build": {"frontendDist": ["./frontend/index.html"]},"app": {"windows": [{"label": "main","title": "start","width": 800,"height": 600,"theme": "Dark"}],"security": {"csp": null}},"bundle": {"active": true,"targets": "all"}
}

icons/icon.ico



frontend/index.html


<!doctype html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Welcome to Tauri!</title></head><body><h1>Welcome to Tauri!</h1><form id="form"><input id="name" placeholder="Enter a name..." /><button>Greet</button></form><p id="message"></p><script>const invoke = window.__TAURI_INTERNALS__.invokeconst form = document.querySelector('#form')const nameEl = document.querySelector('#name')const messageEl = document.querySelector('#message')form.addEventListener('submit', async (e) => {e.preventDefault()const name = nameEl.valueconst newMessage = await invoke('greet', { name })messageEl.textContent = newMessage})</script></body>
</html>

build.rs


fn main(){tauri_build::build();
}

编译项目。

文件目录如下

gen目录是自动生成的,里面是和权限有关的文件。

总之,运行

cargo run 

结果如下

没问题,很好。

爬虫分析

进入spiderdemo第21题的页面后,直言的说,多次点击下一页,可以发现有四个参数进行了加密

两个在请求头中,两个是请求参数。

搜索关键字——x-request-token

直接就发现了关键信息,可以发现

hmac、md5、sha256、sha3_256四种加密方式

所在的文件是hask_challengen.js,把这个文件下载下来。

而且查看页面源代码ctrl+u,可以发现

使用的加密库都写出来了。

这就很简单了,笔者专门选这道题,主要是因为很简单。哈哈哈哈哈哈。

下面对关键代码进行分析

  const t = e.url.match(/\/page\/(\d+)\//);if (t) {const n = parseInt(t[1]),s = new URLSearchParams(e.url.split("?")[1] || "").get("challenge_type") || "hash_challenge",a = Date.now(), o = r(n, s, a);e.headers["X-Request-Token"] = o.hmac, e.headers["X-Verify-Code"] = o.md5;const c = e.url.includes("?") ? "&" : "?";e.url += `${c}sign=${o.sha256}&code=${o.sha3_256}&t=${a}`}

首先,t是什么?可以看出显示t是页数page。但是t是一个字符串

然后解析成数字,n也是页数,n是数字。

s说白就是hash_challenge这个字符串,

a是13位的时间戳,

o是r函数返回,r是什么???

r说白了,就是调用加密函数,很好。

既然如此,笔者可以把r这个函数,变成window对象,即

window.r=r

编写html

经过对js的分析,很容易得到

 X-Request-Token使用hmac,X-Verify-Code使用md5,sign使用sha256,code使用sha3_256

直接给出代码

<!doctype html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>spiderdemo t21</title></head><script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/js-sha3/0.8.0/sha3.min.js"></script><script src="hash_challenge.js"></script><script>function handleClicked(){let page=1;let s = "hash_challenge";let a = Date.now();let o = window.r(page, s, a);let result={"X-Request-Token":o.hmac,"X-Verify-Code":o.md5,"sign":o.sha256,"code":o.sha3_256}console.log(result)}</script><body><button onclick="handleClicked()">确定</button></body>
</html>

可以先直接运行html文件,结果如下

可以发现得到了参数。

最后,修改获取参数的方法,通过tauri的触发

    function get_encrypt_result(page, timestamp) {let s = "hash_challenge";let o = window.r(page, s, timestamp);return {"X-Request-Token": o.hmac,"X-Verify-Code": o.md5,"sign": o.sha256,"code": o.sha3_256,"t":timestamp.toString()}}

需要传入两个参数,一个page,另一个timestamp

Rust爬虫

想简单点,必然需要调用get_encrypt_result方法

其实,笔者在这里考虑了许久,笔者希望tauir调用js,虽然可以调用js,但是无法回去调用后的返回值。

如果硬要获取,感觉很麻烦,笔者没尝试。

最后笔者还是决定使用这个过程

  1. 前端执行加密函数,获取参数
  2. 把参数通过通信函数传入到rust
  3. rust中根据参数编写爬虫
  4. 爬虫结果返回到前端

rust要编写爬虫,不得不使用reqwest

reqwest = {version = "0.12.24",features = ["json", "cookies"] }

写通信函数

考虑通信函数的参数,第一个参数是前面的一个对象,里面有5个参数,然后把页数也作为参数

因此,首先,先定义一个Params结构体

需要实现反序列化,

#[derive(Debug, Deserialize)]
pub struct Params {#[serde(rename = "X-Request-Token")]pub x_request_token:String,#[serde(rename = "X-Verify-Code")]pub x_verify_code: String,pub sign: String,pub code: String,pub t:String,
}

返回值——返回一个数字

因此,定义的通信函数如下

#[tauri::command]
async fn get_result(params: Params,page:u32)->Result<u32, String>{
}

名字任取,笔者取名get_result。

前端加密

直接给出代码

<script type="module">const invoke = window.__TAURI_INTERNALS__.invokeasync function get_params() {let total=0;for (let page = 1; page < 2; page++) {let params = get_encrypt_result(page, Date.now())let one_page_result=await invoke("get_result",{params,page})total+=one_page_result}return total}get_params().then(data=>alert(data))
</script>

定义了一个get_params函数,循环100页,笔者这里只是获取第一页,这不重要,后面改一下页数即可。

调用加密,调用通信函数,返回一页的求和结果,加到最后的结果上。

可以在通信函数里面打印一下params

println!("{params:#?}");

如下

没问题

设置请求头

需要使用reqwest里面的headermap

直接给出代码

use reqwest::header::{HeaderMap,HeaderValue};
fn get_headers(params: &Params) -> HeaderMap {let mut headers = HeaderMap::new();headers.insert("Cookie",HeaderValue::from_static("sessionid=你的sesssionid"));headers.insert("X-Request-Token",HeaderValue::from_str(&params.x_request_token).unwrap());headers.insert("X-Verify-Code",HeaderValue::from_str(&params.x_verify_code).unwrap());headers.insert("User-Agent",HeaderValue::from_static("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0"));headers
}

出来响应

爬虫获取结果之后,怎么处理数据

可以发现,需要page_data里面的数据,而这个page_data又是一个列表,因此,定义一个结构体处理响应的数据

#[derive(Serialize,Deserialize,Debug)]
struct Response {page_data:Vec<u32>
}

发送请求

来到最关键的一步,首先,确定发送get请求,需要传入页数和加密参数,考虑处理结果,考虑请求头,这里不多废话,前面已经做好铺垫,直接给出代码

async fn get_data(params: &Params,page:u32) -> Result<u32, Box<dyn std::error::Error>> {let url = format!("https://www.spiderdemo.cn/authentication/api/hash_challenge/page/{}/",page);let client = Client::new();let resp = client.get(url).headers(get_headers(params)).query(&[("challenge_type", "hash_challenge"),("t", &params.t),("code", &params.code),("sign",&params.sign)]).send().await?.json::<Response>().await?;let total: u32 = resp.page_data.iter().sum();println!("total: {}", total);Ok(total)
}

完善通信函数

注册通信函数,完善代码如下


#[tauri::command]
async fn get_result(params: Params,page:u32)->Result<u32, String>{println!("{params:#?}");let total=get_data(&params,page).await.expect("Error getting data");Ok(total)
}

运行

结果如下

没问题,那么,获取100页的数据,提交。

没问题。

代码

main.rs的代码如下

#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use serde::{Deserialize, Serialize};
use reqwest::Client;
use reqwest::header::{HeaderMap,HeaderValue};#[derive(Debug, Deserialize)]
pub struct Params {#[serde(rename = "X-Request-Token")]pub x_request_token:String,#[serde(rename = "X-Verify-Code")]pub x_verify_code: String,pub sign: String,pub code: String,pub t:String,
}
#[derive(Serialize,Deserialize,Debug)]
struct Response {page_data:Vec<u32>
}
fn get_headers(params: &Params) -> HeaderMap {let mut headers = HeaderMap::new();headers.insert("Cookie",HeaderValue::from_static("sessionid=ub6zyoe3zq0wjgeeyf7ucr0dlso5zgpu"));headers.insert("X-Request-Token",HeaderValue::from_str(&params.x_request_token).unwrap());headers.insert("X-Verify-Code",HeaderValue::from_str(&params.x_verify_code).unwrap());headers.insert("User-Agent",HeaderValue::from_static("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0"));headers
}
async fn get_data(params: &Params,page:u32) -> Result<u32, Box<dyn std::error::Error>> {let url = format!("https://www.spiderdemo.cn/authentication/api/hash_challenge/page/{}/",page);let client = Client::new();let resp = client.get(url).headers(get_headers(params)).query(&[("challenge_type", "hash_challenge"),("t", &params.t),("code", &params.code),("sign",&params.sign)]).send().await?.json::<Response>().await?;let total: u32 = resp.page_data.iter().sum();Ok(total)
}#[tauri::command]
async fn get_result(params: Params,page:u32)->Result<u32, String>{let total=get_data(&params,page).await.expect("Error getting data");Ok(total)
}fn main() {tauri::Builder::default().invoke_handler(tauri::generate_handler![get_result]).run(tauri::generate_context!()).expect("error");
}

index.html的代码如下

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>spiderdemo t21</title>
</head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-sha3/0.8.0/sha3.min.js"></script>
<script src="hash_challenge.js"></script>
<script>function get_encrypt_result(page, timestamp) {let s = "hash_challenge";let o = window.r(page, s, timestamp);return {"X-Request-Token": o.hmac,"X-Verify-Code": o.md5,"sign": o.sha256,"code": o.sha3_256,"t":timestamp.toString()}}
</script><script type="module">const invoke = window.__TAURI_INTERNALS__.invokeasync function get_params() {let total=0;for (let page = 1; page < 101; page++) {let params = get_encrypt_result(page, Date.now())let one_page_result=await invoke("get_result",{params,page})total+=one_page_result}return total}get_params().then(data=>alert(data))
</script>
<body>
</body>
</html>

总结

感觉搞复杂了,在爬虫层面,没有使用python简单,但是使用tauri作为作为执行js并且能交互rust的工具,还是没问题。

最后,推荐下载tauri-cli这个依赖库

cargo install tauri-cli

然后可以执行cargo tauri dev命令,可以热重载。

http://www.dtcms.com/a/550515.html

相关文章:

  • 网站制做工具郑州网站设计有哪些
  • 山东网站建设比较好wordpress安装提示500错误
  • 安卓/ios辅助工具按键精灵脚本制作教程,移动开发工具
  • Python 内置函数
  • 网站建设七个步骤做移动端网站设计
  • 浙江久天建设有限公司网站东莞网络公司电话
  • FBH开发用于增材制造的二极管激光模块
  • offer岗位的base地应该怎么选
  • 全国好的深圳网站设计聚美优品返利网站怎么做
  • [特殊字符] ROS 项目日记
  • 点云深度学习:KPFCNN资料分享
  • 网上下载的免费网站模板怎么用目前引流最好的平台
  • 太仓网站制作书生php网站开发视频
  • 英山县住房和城乡建设局网站百度广告电话号码是多少
  • 学习做网站教程现在网站还用asp做
  • 湖北网站中山外贸网站开发
  • 21.1 ChatPPT容器化部署实战:Dockerfile高效构建与CUDA优化全攻略
  • 理论网站建设实施方案干净简约的网站
  • 乾安网站建设公司分类信息网站开发
  • 海口企业自助建站wordpress 页面连接
  • 深入理解Java高并发:从线程模型到性能优化的全景剖析
  • 基于鸿蒙系统开发APP
  • AI Agent开发中RAG与MCP的应用
  • 长沙网站建设技术iis做网站之vps
  • 佛山网站建设服务商58同城推广网站怎么做
  • 做网站wzjseo双鸭山网站开发
  • ClickHouse数据库的表引擎
  • 敏感信息屏蔽(一)【java】
  • 查询网站空间的服务商微网站开发系统
  • 好学校平台网站模板平台官网入口