You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用C#解析Blazor服务端架构网站的动态加载HTML内容

Blazor Server站点课表数据抓取完整实现方案

前置准备

你已经完成的SignalR连接部分需要保证满足以下要求:

  • 已经引用Microsoft.AspNetCore.SignalR.Client包
  • 自定义的blazorpack协议已经正确注册到HubConnectionBuilder
  • 连接建立时携带的UserAgent、Cookie等头部和浏览器请求完全一致,避免被服务端拦截

ComponentHub初始化核心逻辑

Blazor Server的ComponentHub调用必须严格遵循以下时序,缺少任意一步都会导致请求被忽略:

  1. 发送启动握手包
    连接建立后首先要调用*StartCircuit*方法,传入从初始HTML页面中提取的blazor.server.js初始化参数:
    • 初始HTML中__initialState全局变量对应的序列化状态
    • 页面的uri参数,固定为https://education.khai.edu/union/schedule/
    • 服务端返回的negotiate响应中携带的connectionId
  2. 注册组件渲染回调
    监听*ReceiveJSData、RenderBatch*两个Hub推送方法,所有服务端返回的组件状态、课表数据都会通过这两个方法推送,你需要自己实现反序列化逻辑解析blazor格式的渲染批次数据。
  3. 触发课表查询组件事件
    完成电路初始化后,调用*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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 02:36:07