使用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
相关产品推荐
相关产品推荐

