fish2018/pansou · error
[ ] 解析搜索页面失败
Error message
[%s] 解析搜索页面失败: %w
What it means
This error means goquery could not parse the HTML body of a successful zhizhen search response into a document. NewDocumentFromReader fails on body read errors (truncated connection) or, rarely, empty/unreadable input. The request itself succeeded with status 200, so this points to a corrupt or empty response payload.
Solutions
- Read the body with io.ReadAll first and log its length/snippet to diagnose.
- Re-run against another base URL — searchImpl's mirror fallback handles transient corruption.
- Ensure the transport handles gzip (DefaultTransport does when Accept-Encoding is unset).
- Retry the request; truncation is usually transient.
- Check goquery version for known parsing issues.
Example fix
// before
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return nil, fmt.Errorf("[%s] 解析搜索页面失败: %w", p.Name(), err)
}
// after
body, readErr := io.ReadAll(resp.Body)
if readErr != nil {
return nil, fmt.Errorf("[%s] 读取搜索页面失败: %w", p.Name(), readErr)
}
doc, err := goquery.NewDocumentFromReader(bytes.NewReader(body)) Defensive patterns
Strategy: try-catch
Try / catch
results, err := searchAtBase(client, baseURL, keyword)
if err != nil {
if strings.Contains(err.Error(), "解析搜索页面失败") {
return searchAtBase(client, otherBaseURL, keyword) // corrupt body — retry other mirror
}
return nil, err
} Prevention
- Read body into memory before parsing to detect truncation
- Treat empty bodies as explicit errors
- Retry parse failures against another mirror
- Verify gzip handling when using custom Transports
When it happens
Trigger: goquery.NewDocumentFromReader(resp.Body) returns err in searchAtBase — connection reset mid-body, chunked encoding error, or empty body from the mirror.
Common situations: Unstable mirror closing connections early, proxy interference, gzip/deflate mis-negotiation, or the server replying 200 with an empty body under load.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/a789725400dcea80.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/zhizhen/zhizhen.go:229
req.Header.Set("Upgrade-Insecure-Requests", "1")
req.Header.Set("Cache-Control", "max-age=0")
req.Header.Set("Referer", strings.TrimRight(baseURL, "/")+"/")
// 5. 发送请求(带重试机制)
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("[%s] 搜索请求返回状态码: %d", p.Name(), resp.StatusCode)
}
// 6. 解析搜索结果页面
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return nil, fmt.Errorf("[%s] 解析搜索页面失败: %w", p.Name(), err)
}
// 7. 提取搜索结果
var results []model.SearchResult
doc.Find(".module-search-item").Each(func(i int, s *goquery.Selection) {
result := p.parseSearchItem(s, keyword)
if result.UniqueID != "" {
results = append(results, result)
}
})
return results, nil
}
// parseSearchItem 解析单个搜索结果项
func (p *ZhizhenAsyncPlugin) parseSearchItem(s *goquery.Selection, keyword string) model.SearchResult {
result := model.SearchResult{}View on GitHub (pinned to beaa561337)