{"record":{"id":"dc92bb3b72b59b1a","repo":"fish2018/pansou","slug":"s-html-w-dc92bb","errorCode":null,"errorMessage":"[%s] HTML解析失败: %w","messagePattern":"\\[(.+?)\\] HTML解析失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/qingying/qingying.go","lineNumber":143,"sourceCode":"\t}\n\t\n\tp.setHeaders(req, baseURL)\n\t\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err)\n\t}\n\tdefer resp.Body.Close()\n\t\n\tdebugPrintf(\"📡 HTTP状态码: %d\\n\", resp.StatusCode)\n\t\n\tif resp.StatusCode != 200 {\n\t\treturn nil, fmt.Errorf(\"[%s] 请求返回状态码: %d\", p.Name(), resp.StatusCode)\n\t}\n\t\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] HTML解析失败: %w\", p.Name(), err)\n\t}\n\t\n\tvar items []searchItem\n\tdoc.Find(\"div.module-search-item\").Each(func(i int, s *goquery.Selection) {\n\t\tlink := s.Find(\".video-info .video-info-header h3 a\")\n\t\thref, exists := link.Attr(\"href\")\n\t\tif !exists {\n\t\t\tdebugPrintf(\"⚠️ 第%d个结果没有href属性\\n\", i+1)\n\t\t\treturn\n\t\t}\n\t\t\n\t\ttitle := strings.TrimSpace(link.Text())\n\t\tif title == \"\" {\n\t\t\ttitle, _ = link.Attr(\"title\")\n\t\t\ttitle = strings.TrimSpace(title)\n\t\t}\n\t\t\n\t\tif title == \"\" {","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/qingying/qingying.go#L125-L161","documentation":"goquery.NewDocumentFromReader failed parsing the search response body. goquery returns errors from reading the body stream, not from HTML syntax, so this indicates the response body could not be read (truncated connection, decompression failure, or consumed stream).","triggerScenarios":"Reading resp.Body fails after a 200 response: connection reset mid-body, gzip/br content not decoded (Accept-Encoding set manually), or body partially consumed before parsing.","commonSituations":"A proxy or anti-bot layer returned an encoded/compressed body the client didn't decode; flaky network truncating the page; debug logging code accidentally reading resp.Body before goquery.","solutions":["Retry the request; truncation is often transient.","Remove manual Accept-Encoding headers or enable automatic decompression on the http.Transport.","Buffer the body with io.ReadAll first so it can be logged on failure and parsed from memory.","Check for middleware/debug code reading resp.Body earlier and replace with io.TeeReader."],"exampleFix":"// before\ndoc, err := goquery.NewDocumentFromReader(resp.Body)\nif err != nil {\n    return nil, fmt.Errorf(\"[%s] HTML解析失败: %w\", p.Name(), err)\n}\n// after\nbody, rerr := io.ReadAll(resp.Body)\nif rerr != nil {\n    return nil, fmt.Errorf(\"[%s] 读取响应体失败: %w\", p.Name(), rerr)\n}\ndoc, err := goquery.NewDocumentFromReader(bytes.NewReader(body))","handlingStrategy":"retry","validationCode":"body, err := io.ReadAll(resp.Body)\nif err != nil || len(bytes.TrimSpace(body)) == 0 {\n    return // empty/truncated body, retry\n}","typeGuard":"func isBodyReadError(err error) bool {\n    return err != nil && (errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF))\n}","tryCatchPattern":"results, err := plugin.Search(keyword)\nif err != nil && strings.Contains(err.Error(), \"HTML解析失败\") {\n    select {\n    case <-time.After(5 * time.Second):\n        return plugin.Search(keyword) // one retry for transient body errors\n    }\n}","preventionTips":["Enable automatic decompression on the transport instead of manual Accept-Encoding.","Buffer bodies with io.ReadAll before parsing for easier diagnostics.","Never read resp.Body before goquery (use io.TeeReader for logging).","Retry read failures with a short backoff — they're usually transient."],"tags":["html-parsing","goquery","io","compression"],"backgroundTag":"html-parse-failed","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}