fish2018/pansou · warning
[ ] 解析搜索结果失败
Error message
[%s] 解析搜索结果失败: %w
What it means
fetchSearch wraps an error from goquery.NewDocumentFromReader(strings.NewReader(decoded)) — parsing the UTF-8 HTML into a document failed. goquery only errors if the underlying charset reader cannot be constructed or the HTML parser fails on malformed input; in practice this is extremely rare because Go's HTML parser is lenient with broken markup.
Solutions
- Confirm decodeGB18030 output is valid UTF-8 (utf8.Valid) and log a prefix of the decoded string to see what is actually being parsed.
- If invalid UTF-8 is possible, sanitize with strings.ToValidUTF8 before parsing.
- Log the decoded body on failure to check whether the site is returning a challenge page instead of search results.
- Upgrade goquery (github.com/PuerkitoBio/goquery) to the latest version if parsing genuinely fails on valid HTML.
Example fix
// before
doc, err := goquery.NewDocumentFromReader(strings.NewReader(decoded))
if err != nil {
return nil, fmt.Errorf("[%s] 解析搜索结果失败: %w", p.Name(), err)
}
// after
if !utf8.ValidString(decoded) {
decoded = strings.ToValidUTF8(decoded, "")
}
doc, err := goquery.NewDocumentFromReader(strings.NewReader(decoded))
if err != nil {
return nil, fmt.Errorf("[%s] 解析搜索结果失败: %w", p.Name(), err)
} Defensive patterns
Strategy: validation
Validate before calling
if !utf8.ValidString(decoded) {
decoded = strings.ToValidUTF8(decoded, "")
}
// 再传给 goquery Type guard
func isParsableHTML(s string) bool {
return utf8.ValidString(s) && strings.Contains(strings.ToLower(s[:min(2048, len(s))]), "<")
} Try / catch
doc, err := goquery.NewDocumentFromReader(strings.NewReader(decoded))
if err != nil {
// 记录 decoded 前 512 字节便于诊断, 然后降级为空结果
return nil, fmt.Errorf("解析失败: %w", err)
} Prevention
- Sanitize decoder output to valid UTF-8 before parsing.
- Log page content on parse failure to detect challenge pages.
- Keep goquery up to date.
- Treat parse errors as a symptom of upstream (decode/network) problems.
When it happens
Trigger: goquery.NewDocumentFromReader returns err: the decoded string is not valid input for the HTML parser — practically only when decodeGB18030 produced invalid UTF-8 or garbage rather than HTML, since goquery tolerates malformed tags.
Common situations: A previous decoding step (charset-decode-failed family) silently produced invalid UTF-8 that now breaks parsing; an anti-bot page with binary/JS-challenge content is fed to the parser; a goquery version regression on pathological input.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/9ef0435d874cb20a.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/5266ys/5266ys.go:198
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("[%s] 搜索请求返回 HTTP %d", p.Name(), resp.StatusCode)
}
body, err := io.ReadAll(io.LimitReader(resp.Body, 4<<20))
if err != nil {
return nil, fmt.Errorf("[%s] 读取搜索结果失败: %w", p.Name(), err)
}
decoded, err := decodeGB18030(body)
if err != nil {
return nil, fmt.Errorf("[%s] 解码搜索结果失败: %w", p.Name(), err)
}
doc, err := goquery.NewDocumentFromReader(strings.NewReader(decoded))
if err != nil {
return nil, fmt.Errorf("[%s] 解析搜索结果失败: %w", p.Name(), err)
}
return doc, nil
}
func (p *Plugin) fetchDetail(client *http.Client, detailURL string) ([]magnetItem, string, string) {
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, detailURL, nil)
if err != nil {
return nil, "", ""
}
setHeaders(req, baseURL+"/")
resp, err := client.Do(req)
if err != nil {
return nil, "", ""
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {View on GitHub (pinned to beaa561337)