{"record":{"id":"d00be829e87785cb","repo":"fish2018/pansou","slug":"html-w-d00be8","errorCode":null,"errorMessage":"详情页HTML解析失败: %w","messagePattern":"详情页HTML解析失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/pianku/pianku.go","lineNumber":405,"sourceCode":"\t// 设置请求头\n\tp.setRequestHeaders(req)\n\t\n\t// 发送HTTP请求\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"详情页请求失败: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\t\n\t// 检查状态码\n\tif resp.StatusCode != 200 {\n\t\treturn nil, fmt.Errorf(\"详情页请求返回状态码: %d\", resp.StatusCode)\n\t}\n\t\n\t// 解析HTML\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"详情页HTML解析失败: %w\", err)\n\t}\n\t\n\t// 提取下载链接\n\treturn p.extractDownloadLinks(doc), nil\n}\n\n// extractDownloadLinks 提取详情页中的下载链接\nfunc (p *PiankuPlugin) extractDownloadLinks(doc *goquery.Document) []model.Link {\n\tvar links []model.Link\n\tseenURLs := make(map[string]bool) // 用于去重\n\t\n\t// 查找下载链接区域\n\tdoc.Find(\"#donLink .down-list2\").Each(func(i int, s *goquery.Selection) {\n\t\tlinkURL, exists := s.Find(\".down-list3 a\").Attr(\"href\")\n\t\tif !exists || linkURL == \"\" {\n\t\t\treturn\n\t\t}\n\t\t","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/pianku/pianku.go#L387-L423","documentation":"goquery.NewDocumentFromReader failed while parsing the detail-page response body into an HTML document. goquery returns this error when reading the body stream fails (goquery itself does not validate HTML; malformed HTML still parses leniently).","triggerScenarios":"Reading resp.Body returned an I/O error: connection dropped mid-body, gzip/deflate decompression failure due to a corrupted or truncated response, or the body was already partially consumed.","commonSituations":"Unstable network cutting the response short; server advertises Content-Encoding: gzip but sends invalid data; a proxy mangling the response; very large pages hitting an underlying read limit.","solutions":["Retry the request — a truncated body is usually transient network corruption.","Ensure automatic decompression: set Transport.DisableCompression=false or use httputil to handle gzip; don't set Accept-Encoding manually without decoding.","Check that resp.Body wasn't read before this call (e.g. by a debug logger).","Capture and log the underlying read error (errors.Unwrap) to confirm I/O vs decompression."],"exampleFix":"// before\ndoc, err := goquery.NewDocumentFromReader(resp.Body)\nif err != nil {\n    return nil, fmt.Errorf(\"详情页HTML解析失败: %w\", err)\n}\n// after\nbody, rerr := io.ReadAll(resp.Body)\nif rerr != nil {\n    return nil, fmt.Errorf(\"读取详情页响应体失败: %w\", rerr)\n}\ndoc, err := goquery.NewDocumentFromReader(bytes.NewReader(body))\nif err != nil {\n    return nil, fmt.Errorf(\"详情页HTML解析失败: %w\", err)\n}","handlingStrategy":"retry","validationCode":"body, err := io.ReadAll(resp.Body)\nif err != nil || len(body) == 0 {\n    return // truncated/empty body, retry the request\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    // transient I/O on the body: retry once\n    results, err = plugin.Search(keyword)\n}","preventionTips":["Let the http.Transport handle gzip/deflate; don't set Accept-Encoding manually.","Buffer the response body before parsing so failures are diagnosable.","Avoid reading resp.Body anywhere before goquery.","Retry body-read failures; they are usually transient network truncation."],"tags":["html-parsing","goquery","io","network"],"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"}