{"record":{"id":"9332d0c2610e59b4","repo":"fish2018/pansou","slug":"s-html-w-9332d0","errorCode":null,"errorMessage":"[%s] 解析搜索结果HTML失败: %w","messagePattern":"\\[(.+?)\\] 解析搜索结果HTML失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/javdb/javdb.go","lineNumber":237,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 读取搜索结果失败: %w\", p.Name(), err), false\n\t}\n\n\tif p.debugMode {\n\t\tbodyStr := string(bodyBytes)\n\t\tlog.Printf(\"[JAVDB] 响应体长度: %d\", len(bodyStr))\n\t\t// 输出前500个字符用于调试\n\t\tif len(bodyStr) > 500 {\n\t\t\tlog.Printf(\"[JAVDB] 响应体前500字符: %s\", bodyStr[:500])\n\t\t} else {\n\t\t\tlog.Printf(\"[JAVDB] 完整响应体: %s\", bodyStr)\n\t\t}\n\t}\n\n\t// 解析HTML提取搜索结果\n\tdoc, err := goquery.NewDocumentFromReader(strings.NewReader(string(bodyBytes)))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 解析搜索结果HTML失败: %w\", p.Name(), err), false\n\t}\n\n\tresults, err := p.parseSearchResults(doc)\n\treturn results, err, false\n}\n\n\n// doRequestWithRetry 带重试机制的HTTP请求\nfunc (p *JavdbPlugin) doRequestWithRetry(req *http.Request, client *http.Client) (*http.Response, error) {\n\tmaxRetries := 3\n\tvar lastErr error\n\t\n\tfor i := 0; i < maxRetries; i++ {\n\t\tif i > 0 {\n\t\t\t// 指数退避重试\n\t\t\tbackoff := time.Duration(1<<uint(i-1)) * 200 * time.Millisecond\n\t\t\ttime.Sleep(backoff)\n\t\t}","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/javdb/javdb.go#L219-L255","documentation":"executeSearchWithRateLimit returns '[javdb] 解析搜索结果HTML失败: %w' (failed to parse search results HTML) when goquery.NewDocumentFromReader fails to parse the fetched body as HTML. With goquery this is rare and almost always means the reader itself errored, but it signals the response could not be turned into a parseable document.","triggerScenarios":"goquery.NewDocumentFromReader returns an error on the bodyBytes reader — typically because the body is empty/corrupt or the underlying reader fails, after a successful (but wrong) response was fetched.","commonSituations":"Site returns a non-HTML body (JSON error, compressed/garbled bytes when Content-Encoding handling is broken, empty body from a soft block) that the HTML parser chokes on.","solutions":["Log the first bytes/Content-Type of bodyBytes when this fires to see what was actually returned","Verify automatic gzip/deflate decompression (check Content-Encoding handling in the transport)","Check for soft-block pages (challenge/JS) that are not real search HTML","Guard against empty bodies before parsing and return a clearer 'empty response' error","Update selectors/endpoint if the site changed its HTML contract"],"exampleFix":"// before\ndoc, err := goquery.NewDocumentFromReader(strings.NewReader(string(bodyBytes)))\n// after\nif len(bodyBytes) == 0 {\n    return nil, fmt.Errorf(\"[%s] empty response body\", p.Name()), false\n}\ndoc, err := goquery.NewDocumentFromReader(strings.NewReader(string(bodyBytes)))","handlingStrategy":"validation","validationCode":"// Go: sanity-check the body before HTML parsing\nct := resp.Header.Get(\"Content-Type\")\nif !strings.Contains(ct, \"text/html\") {\n    return fmt.Errorf(\"unexpected content-type %q\", ct)\n}\nif len(bodyBytes) == 0 {\n    return errors.New(\"empty response body\")\n}","typeGuard":"func looksLikeHTML(b []byte) bool {\n    s := strings.TrimSpace(string(b))\n    return len(s) > 0 && (strings.HasPrefix(s, \"<\") || strings.Contains(s[:min(200, len(s))], \"<html\"))\n}","tryCatchPattern":"doc, err := goquery.NewDocumentFromReader(bytes.NewReader(bodyBytes))\nif err != nil {\n    log.Printf(\"javdb html parse failed, body head=%q\", bodyBytes[:min(200, len(bodyBytes))])\n    return nil, err, false\n}","preventionTips":["Verify Content-Encoding/decompression is handled (garbled bodies break parsers)","Check Content-Type before parsing","Log a body snippet on parse failure to detect soft-block pages","Update selectors when the site changes markup"],"tags":["html-parsing","goquery","scraping","go"],"backgroundTag":"invalid-html-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"}