如何使用C#解析Blazor服务端架构网站的动态加载HTML内容
Blazor Server站点课表数据抓取完整实现方案
前置准备
你已经完成的SignalR连接部分需要保证满足以下要求:
- 已经引用
Microsoft.AspNetCore.SignalR.Client包 - 自定义的blazorpack协议已经正确注册到HubConnectionBuilder
- 连接建立时携带的UserAgent、Cookie等头部和浏览器请求完全一致,避免被服务端拦截
ComponentHub初始化核心逻辑
Blazor Server的ComponentHub调用必须严格遵循以下时序,缺少任意一步都会导致请求被忽略:
- 发送启动握手包
连接建立后首先要调用*StartCircuit*方法,传入从初始HTML页面中提取的blazor.server.js初始化参数:- 初始HTML中
__initialState全局变量对应的序列化状态 - 页面的
uri参数,固定为https://education.khai.edu/union/schedule/ - 服务端返回的
negotiate响应中携带的connectionId
- 初始HTML中
- 注册组件渲染回调
监听*ReceiveJSData、RenderBatch*两个Hub推送方法,所有服务端返回的组件状态、课表数据都会通过这两个方法推送,你需要自己实现反序列化逻辑解析blazor格式的渲染批次数据。 - 触发课表查询组件事件
完成电路初始化后,调用*DispatchBrowserEvent*方法模拟页面上的查询按钮点击/下拉框选择事件,事件参数需要和浏览器中捕获的参数完全一致:- 事件类型固定为
click或者change(对应你要触发的表单元素) - 事件所属的组件id可以从浏览器DevTools的SignalR帧中捕获
- 表单提交的参数(学生id、学期、年份等)要序列化后放到事件的
eventArgs字段中
- 事件类型固定为
完整C#代码示例
using Microsoft.AspNetCore.SignalR.Client; using System.Text.Json; // 1. 构建连接 var connection = new HubConnectionBuilder() .WithUrl("https://education.khai.edu/_blazor", opts => { opts.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"); // 补充你从浏览器中复制的Cookie头 opts.Headers.Add("Cookie", "你的Cookie值"); }) .AddProtocol(new CustomBlazorPackHubProtocol()) // 你自己实现的blazorpack协议 .Build(); // 2. 监听服务端推送 connection.On<byte[]>("RenderBatch", batch => { // 解析渲染批次,提取课表数据 var scheduleData = ParseBlazorRenderBatch(batch); Console.WriteLine(JsonSerializer.Serialize(scheduleData)); }); // 3. 启动连接 await connection.StartAsync(); // 4. 初始化Circuit var initialState = "你从初始HTML中提取的__initialState值"; var circuitId = await connection.InvokeAsync<string>("StartCircuit", initialState, "https://education.khai.edu/union/schedule/", connection.ConnectionId); // 5. 触发课表查询事件 // 以下参数请从浏览器SignalR捕获的帧中替换为实际有效值 await connection.InvokeVoidAsync("DispatchBrowserEvent", new { EventId = 1, EventName = "change", ComponentId = 12, // 下拉框对应的组件ID EventArgs = new { Value = "你的学生ID" } }); // 保持连接直到获取到数据 await Task.Delay(5000); await connection.StopAsync(); // 渲染批次解析方法实现 object ParseBlazorRenderBatch(byte[] batchData) { // 参照blazor.server.js中的RenderBatchReader实现反序列化逻辑 // 提取对应课表组件的属性值即可得到结构化的课表数据 return new object(); } // 你自己实现的BlazorPack协议类 class CustomBlazorPackHubProtocol : IHubProtocol { // 实现对应协议逻辑即可 }
注意事项
- 所有请求参数必须和浏览器实际发送的完全一致,包括组件ID、事件参数结构,服务端会做严格校验
- Circuit有超时时间,连接建立后需要在30秒内完成初始化和事件触发,否则需要重新建立连接
- 如果返回的渲染批次是压缩格式,需要先做gzip解压再解析
内容的提问来源于stack exchange,提问作者iikuzmychov
相关产品推荐
相关产品推荐

