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

PuppeteerSharp拦截GET请求时触发“Request interception is not enabled!”错误求助

PuppeteerSharp 请求拦截报错:Request Interception is not enabled! 及任务状态重复设置问题

问题根源

  1. 请求拦截关闭后仍有回调执行:调用await page.SetRequestInterceptionAsync(false)后,之前注册的Request事件回调可能还在后台异步处理未完成的请求,此时调用e.Request.ContinueAsync()会因拦截功能已禁用而抛出异常。
  2. TaskCompletionSource重复赋值:页面加载过程中可能触发多个媒体请求,多次调用tcs.SetResult(audioUrl)会导致任务状态重复转换,引发InvalidOperationException。

修复方案

  • 先取消Request事件的订阅,再关闭请求拦截,避免回调继续执行。
  • 给TaskCompletionSource添加状态判断,确保只设置一次结果。
  • 媒体请求拦截后,必须调用ContinueAsync()或AbortAsync(),防止请求挂起影响后续流程。

修正后的代码

调用请求拦截的核心代码

await page.SetRequestInterceptionAsync(true);
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
// 保存事件委托,用于后续取消订阅
EventHandler<RequestEventArgs> requestHandler = null;

requestHandler = async (sender, e) =>
{
    try
    {
        if (e.Request.ResourceType != ResourceType.Media)
        {
            await e.Request.ContinueAsync();
        }
        else
        {
            // 确保只设置一次结果
            if (!tcs.Task.IsCompleted)
            {
                string audioUrl = e.Request.Url;
                tcs.SetResult(audioUrl);
            }
            // 继续请求,避免浏览器挂起
            await e.Request.ContinueAsync();
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
        // 确保只设置一次异常
        if (!tcs.Task.IsCompleted)
        {
            tcs.SetException(ex);
        }
    }
};

page.Request += requestHandler;

try
{
    await page.GoToAsync(links[i], new NavigationOptions { Timeout = 5000, WaitUntil = new[] { WaitUntilNavigation.DOMContentLoaded } });
    string audioUrl = await tcs.Task;
    // 在这里处理音频URL,比如执行下载逻辑
}
finally
{
    // 先取消事件订阅,再关闭请求拦截,彻底切断回调
    page.Request -= requestHandler;
    await page.SetRequestInterceptionAsync(false);
}

封装后的拦截方法(可选)

如果需要保留方法形式,可以将拦截逻辑封装为返回委托的函数:

public static EventHandler<RequestEventArgs> SetupRequestInterception(IPage page, TaskCompletionSource<string> tcs)
{
    EventHandler<RequestEventArgs> handler = async (sender, e) =>
    {
        try
        {
            if (e.Request.ResourceType != ResourceType.Media)
            {
                await e.Request.ContinueAsync();
            }
            else
            {
                if (!tcs.Task.IsCompleted)
                {
                    tcs.SetResult(e.Request.Url);
                }
                await e.Request.ContinueAsync();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            if (!tcs.Task.IsCompleted)
            {
                tcs.SetException(ex);
            }
        }
    };
    page.Request += handler;
    return handler;
}

调用方式:

await page.SetRequestInterceptionAsync(true);
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
var handler = SetupRequestInterception(page, tcs);

try
{
    await page.GoToAsync(links[i], new NavigationOptions { Timeout = 5000, WaitUntil = new[] { WaitUntilNavigation.DOMContentLoaded } });
    string audioUrl = await tcs.Task;
}
finally
{
    page.Request -= handler;
    await page.SetRequestInterceptionAsync(false);
}

关键说明

  • 必须在finally块中执行事件订阅取消和拦截关闭操作,确保无论流程是否异常,都能清理资源。
  • 对TaskCompletionSource的状态判断是核心,避免重复赋值导致的任务状态错误。
  • 媒体请求拦截后必须调用ContinueAsync()或AbortAsync(),否则浏览器会一直等待请求处理,可能引发超时或资源泄漏。

内容的提问来源于stack exchange,提问作者Carbon_Based

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 14:12:43