{"record":{"id":"51b326e54b76682e","repo":"fish2018/pansou","slug":"s-d-w-51b326","errorCode":null,"errorMessage":"[%s] 解析第%d页失败: %w","messagePattern":"\\[(.+?)\\] 解析第(.+?)页失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/yunsou/yunsou.go","lineNumber":134,"sourceCode":"\t\tpath = fmt.Sprintf(\"%s-%d\", pathKeyword, page)\n\t}\n\trequestURL := fmt.Sprintf(searchURLTemplate, path)\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 创建第%d页请求失败: %w\", p.Name(), page, err)\n\t}\n\treq.Header.Set(\"User-Agent\", \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36\")\n\treq.Header.Set(\"Accept\", \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\")\n\treq.Header.Set(\"Accept-Language\", \"zh-CN,zh;q=0.9,en;q=0.8\")\n\treq.Header.Set(\"Referer\", \"https://wpys.cc/\")\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 第%d页搜索请求失败: %w\", p.Name(), page, err)\n\t}\n\tdefer resp.Body.Close()\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 解析第%d页失败: %w\", p.Name(), page, err)\n\t}\n\treturn doc, nil\n}\n\nfunc (p *YunsouAsyncPlugin) doRequestWithRetry(req *http.Request, client *http.Client) (*http.Response, error) {\n\tvar lastErr error\n\tfor attempt := 0; attempt < maxRetries; attempt++ {\n\t\tif attempt > 0 {\n\t\t\ttime.Sleep(time.Duration(1<<(attempt-1)) * 200 * time.Millisecond)\n\t\t}\n\t\tresp, err := client.Do(req.Clone(req.Context()))\n\t\tif err == nil && resp.StatusCode == http.StatusOK {\n\t\t\treturn resp, nil\n\t\t}\n\t\tif resp != nil {\n\t\t\tlastErr = fmt.Errorf(\"状态码 %d\", resp.StatusCode)\n\t\t\tresp.Body.Close()\n\t\t} else {","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/yunsou/yunsou.go#L116-L152","documentation":"This error means goquery failed to parse the HTTP response body of a yunsou search page into an HTML document. goquery.NewDocumentFromReader fails mainly when the body cannot be read (I/O error) or produces invalid/unparseable HTML. Because fetchPage already confirmed HTTP 200, this usually indicates a truncated or corrupt response.","triggerScenarios":"goquery.NewDocumentFromReader(resp.Body) returns a non-nil error in fetchPage — response body read error, connection dropped mid-transfer, or body is empty/garbage.","commonSituations":"Proxy or CDN cutting the response short, server returning compressed content with broken Content-Encoding, or a captive portal returning malformed HTML.","solutions":["Log part of resp.Body content to confirm what was actually received.","Check Content-Encoding/gzip handling; ensure the http.Client transport decompresses (DisableCompression=false).","Re-run the request — transient truncation is common; rely on the existing retry wrapper.","Verify the site still serves the expected HTML page and not an error/challenge page.","Upgrade goquery if using a very old version with parsing bugs."],"exampleFix":"// before\ndoc, err := goquery.NewDocumentFromReader(resp.Body)\nif err != nil {\n    return nil, fmt.Errorf(\"[%s] 解析第%d页失败: %w\", p.Name(), page, err)\n}\n// after\nbody, readErr := io.ReadAll(resp.Body)\nif readErr != nil || len(bytes.TrimSpace(body)) == 0 {\n    return nil, fmt.Errorf(\"[%s] 第%d页响应体为空或读取失败: %w\", p.Name(), page, readErr)\n}\ndoc, err := goquery.NewDocumentFromReader(bytes.NewReader(body))","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"doc, err := fetchPage(client, keyword, page)\nif err != nil {\n    var parseErr interface{ Unwrap() error }\n    log.Printf(\"第%d页不可用: %v\", page, err)\n    continue // skip to next page\n}","preventionTips":["Buffer the body before parsing to detect empty responses","Verify Content-Encoding handling in the transport","Treat empty response body as a distinct error","Retry parsing failures once — truncation is often transient"],"tags":["parsing","html","goquery","http"],"backgroundTag":"json-parse-error","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"}