{"record":{"id":"cf32fd340112b15d","repo":"fish2018/pansou","slug":"s-html-w-cf32fd","errorCode":null,"errorMessage":"[%s] HTML解析失败: %w","messagePattern":"\\[(.+?)\\] HTML解析失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/wuji/wuji.go","lineNumber":209,"sourceCode":"\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err)\n\t}\n\tdefer resp.Body.Close()\n\t\n\t// 检查状态码\n\tif resp.StatusCode != 200 {\n\t\treturn nil, fmt.Errorf(\"[%s] 请求返回状态码: %d\", p.Name(), resp.StatusCode)\n\t}\n\t\n\t// 读取响应体内容\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 读取响应失败: %w\", p.Name(), err)\n\t}\n\t\n\t// 解析HTML\n\tdoc, err := goquery.NewDocumentFromReader(strings.NewReader(string(body)))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] HTML解析失败: %w\", p.Name(), err)\n\t}\n\t\n\t// 提取搜索结果\n\treturn p.extractSearchResults(doc), nil\n}\n\n// extractSearchResults 提取搜索结果\nfunc (p *WujiPlugin) extractSearchResults(doc *goquery.Document) []model.SearchResult {\n\tvar results []model.SearchResult\n\t\n\t// 查找所有搜索结果\n\tdoc.Find(\"table.file-list tbody tr\").Each(func(i int, s *goquery.Selection) {\n\t\tresult := p.parseSearchResult(s)\n\t\tif result.Title != \"\" {\n\t\t\tresults = append(results, result)\n\t\t}\n\t})\n\t","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/wuji/wuji.go#L191-L227","documentation":"searchPage wraps the error from goquery.NewDocumentFromReader, which parses the response body as HTML using the goquery/html parser. goquery's HTML parser is extremely lenient, so this error almost always means the body was not parseable at all — e.g. empty body, binary/compressed content, or garbage — rather than merely malformed markup.","triggerScenarios":"goquery.NewDocumentFromReader(strings.NewReader(string(body))) fails: body is nil/garbled, served with an unexpected content encoding that wasn't decompressed, or the site returned binary data with a 200 status.","commonSituations":"Site changed response format or now serves compressed content without proper Accept-Encoding handling; response body empty because of a silent WAF block; CDN serving an error asset.","solutions":["Log the first bytes / length of body to see what was actually received","Check the Content-Type and Content-Encoding response headers and add gzip handling if needed","Send realistic Accept/Accept-Encoding headers via setRequestHeaders to get proper HTML","Verify the site still serves the expected search HTML (open searchURL in a browser)","If the site's markup changed, update extractSearchResults selectors; the parse error itself usually indicates non-HTML content"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// check response looks like HTML before parsing\ncType := resp.Header.Get(\"Content-Type\")\nif !strings.Contains(cType, \"text/html\") {\n    return fmt.Errorf(\"unexpected content-type: %s\", cType)\n}\nif len(body) == 0 {\n    return fmt.Errorf(\"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":"results, err := p.Search(keyword, ext)\nif err != nil {\n    if strings.Contains(err.Error(), \"HTML解析失败\") {\n        // fall back to another search plugin; log body sample for diagnosis\n    }\n}","preventionTips":["Send explicit Accept: text/html and correct Accept-Encoding headers","Check Content-Type/Content-Encoding before assuming HTML","Log a prefix of the body when parsing fails to detect WAF pages or compression issues","Keep goquery updated; verify site markup after upstream changes"],"tags":["html","parsing","goquery","encoding","go"],"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"}