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

使用goquery获取网页DOM时遇PROTOCOL_ERROR协议错误求助

解决goquery抓取网页时的"stream error: stream ID 1; PROTOCOL_ERROR"问题

这个报错我之前踩过坑,基本都是HTTP/2协议的兼容性问题导致的——默认的http.Get()会优先使用HTTP/2,但有些网站的服务器对HTTP/2的支持有瑕疵,或者会拦截非标准的请求,就会抛出这个协议错误。给你几个靠谱的解决方案:

  • 强制使用HTTP/1.1协议
    直接禁用HTTP/2,改用更通用的HTTP/1.1,大部分情况下能直接解决问题。修改后的代码如下:

    import (
        "net/http"
        "crypto/tls"
        "github.com/PuerkitoBio/goquery"
    )
    
    func getDocument(somedotcom string) (*goquery.Document, error) {
        // 创建自定义Transport,强制使用HTTP/1.1
        transport := &http.Transport{
            TLSClientConfig: &tls.Config{
                NextProtos: []string{"http/1.1"},
            },
        }
        client := &http.Client{Transport: transport}
    
        response, err := client.Get(somedotcom)
        if err != nil {
            return nil, err
        }
        // 一定要记得关闭响应体,避免内存泄漏和连接池问题
        defer response.Body.Close()
    
        doc, err := goquery.NewDocumentFromReader(response.Body)
        if err != nil {
            return nil, err
        }
        return doc, nil
    }
    
  • 模拟浏览器请求头
    有些网站会拒绝看起来像爬虫的请求,这种情况下即使协议没问题,也会触发奇怪的协议错误。你可以给请求加上浏览器的User-Agent等头信息:

    func getDocument(somedotcom string) (*goquery.Document, error) {
        transport := &http.Transport{
            TLSClientConfig: &tls.Config{
                NextProtos: []string{"http/1.1"},
            },
        }
        client := &http.Client{Transport: transport}
    
        req, err := http.NewRequest("GET", somedotcom, nil)
        if err != nil {
            return nil, err
        }
        // 添加浏览器的User-Agent
        req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36")
        // 可选:添加Accept-Language等其他头
        req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
    
        response, err := client.Do(req)
        if err != nil {
            return nil, err
        }
        defer response.Body.Close()
    
        doc, err := goquery.NewDocumentFromReader(response.Body)
        if err != nil {
            return nil, err
        }
        return doc, nil
    }
    
  • 不要忘记关闭响应体
    你的原代码里没有defer response.Body.Close(),这会导致连接池资源泄漏,时间长了也可能引发各种奇怪的网络错误,这个细节一定要注意。

试一下上面的方案,应该能解决你的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:17:39