{"record":{"id":"efc66846c1bbce1e","repo":"fish2018/pansou","slug":"s-w-efc668","errorCode":null,"errorMessage":"[%s] 解析搜索页面失败: %w","messagePattern":"\\[(.+?)\\] 解析搜索页面失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/huban/huban.go","lineNumber":275,"sourceCode":"\treq.Header.Set(\"Accept-Language\", \"zh-CN,zh;q=0.9,en;q=0.8\")\n\treq.Header.Set(\"Connection\", \"keep-alive\")\n\treq.Header.Set(\"Referer\", strings.TrimRight(baseURL, \"/\")+\"/\")\n\n\t// 5. 发送请求\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\n\tif resp.StatusCode != 200 {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求返回状态码: %d\", p.Name(), resp.StatusCode)\n\t}\n\n\t// 6. 解析搜索结果页面\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 解析搜索页面失败: %w\", p.Name(), err)\n\t}\n\n\t// 7. 提取搜索结果\n\tvar results []model.SearchResult\n\n\tdoc.Find(\".module-search-item\").Each(func(i int, s *goquery.Selection) {\n\t\tresult := p.parseSearchItem(s, keyword)\n\t\tif result.UniqueID != \"\" {\n\t\t\tresults = append(results, result)\n\t\t}\n\t})\n\n\treturn results, nil\n}\n\n// parseSearchItem 解析单个搜索结果项\nfunc (p *HubanAsyncPlugin) parseSearchItem(s *goquery.Selection, keyword string) model.SearchResult {\n\tresult := model.SearchResult{}","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/huban/huban.go#L257-L293","documentation":"Wrapped parse error in huban's searchAtBase (plugin/huban/huban.go:275): the search page returned 200 but goquery could not parse it into a document, typically because the body was an anti-bot or error page rather than search HTML. Content-shape failure, not network.","triggerScenarios":"goquery.NewDocumentFromReader(resp.Body) returns a non-nil error during searchAtBase — typically truncated/gzip-corrupted body or an I/O error while reading the response stream.","commonSituations":"镜像站返回压缩/二进制内容；站点改版输出格式变化。","solutions":["Retry the request — the body read failure is often transient network corruption","Verify the response Content-Encoding/Content-Type matches what goquery expects (HTML)","Check whether the site is returning a challenge/blocked page instead of search results","Log the underlying wrapped error (err) for the root cause","Ensure resp.Body is fully consumed only once and not already closed"],"exampleFix":"// before\ndoc, err := goquery.NewDocumentFromReader(resp.Body)\nif err != nil {\n\treturn nil, fmt.Errorf(\"[%s] 解析搜索页面失败: %w\", p.Name(), err)\n}\n// after\ndoc, err := goquery.NewDocumentFromReader(resp.Body)\nif err != nil {\n\treturn nil, fmt.Errorf(\"[%s] 解析搜索页面失败: %w\", p.Name(), err)\n}\nif doc.Find(\".module-search-item\").Length() == 0 {\n\treturn nil, fmt.Errorf(\"[%s] 页面无搜索结果，可能被拦截\", p.Name())\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isParseError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"解析搜索页面失败\")\n}","tryCatchPattern":"results, err := plugin.Search(keyword)\nif isParseError(err) {\n\tlog.Printf(\"search page unparseable, retrying once: %v\", err)\n\tresults, err = plugin.Search(keyword)\n}\nif err != nil { return nil, err }","preventionTips":["Retry parse failures once — body truncation is often transient","Ensure gzip/decompression is handled before goquery parses the body","Log response Content-Type to detect non-HTML challenge pages","Treat zero parsed results as a signal of a blocked/changed page layout"],"tags":["http","html-parsing","goquery","network"],"backgroundTag":"invalid-json-response","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"}