fish2018/pansou · error
[ ] 解析第 页失败
Error message
[%s] 解析第%d页失败: %w
What it means
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.
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.
Example fix
// before
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return nil, fmt.Errorf("[%s] 解析第%d页失败: %w", p.Name(), page, err)
}
// after
body, readErr := io.ReadAll(resp.Body)
if readErr != nil || len(bytes.TrimSpace(body)) == 0 {
return nil, fmt.Errorf("[%s] 第%d页响应体为空或读取失败: %w", p.Name(), page, readErr)
}
doc, err := goquery.NewDocumentFromReader(bytes.NewReader(body)) Defensive patterns
Strategy: try-catch
Try / catch
doc, err := fetchPage(client, keyword, page)
if err != nil {
var parseErr interface{ Unwrap() error }
log.Printf("第%d页不可用: %v", page, err)
continue // skip to next page
} Prevention
- 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
When it happens
Trigger: goquery.NewDocumentFromReader(resp.Body) returns a non-nil error in fetchPage — response body read error, connection dropped mid-transfer, or body is empty/garbage.
Common situations: Proxy or CDN cutting the response short, server returning compressed content with broken Content-Encoding, or a captive portal returning malformed HTML.
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/51b326e54b76682e.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/yunsou/yunsou.go:134
path = fmt.Sprintf("%s-%d", pathKeyword, page)
}
requestURL := fmt.Sprintf(searchURLTemplate, path)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)
if err != nil {
return nil, fmt.Errorf("[%s] 创建第%d页请求失败: %w", p.Name(), page, err)
}
req.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")
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
req.Header.Set("Referer", "https://wpys.cc/")
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return nil, fmt.Errorf("[%s] 第%d页搜索请求失败: %w", p.Name(), page, err)
}
defer resp.Body.Close()
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return nil, fmt.Errorf("[%s] 解析第%d页失败: %w", p.Name(), page, err)
}
return doc, nil
}
func (p *YunsouAsyncPlugin) doRequestWithRetry(req *http.Request, client *http.Client) (*http.Response, error) {
var lastErr error
for attempt := 0; attempt < maxRetries; attempt++ {
if attempt > 0 {
time.Sleep(time.Duration(1<<(attempt-1)) * 200 * time.Millisecond)
}
resp, err := client.Do(req.Clone(req.Context()))
if err == nil && resp.StatusCode == http.StatusOK {
return resp, nil
}
if resp != nil {
lastErr = fmt.Errorf("状态码 %d", resp.StatusCode)
resp.Body.Close()
} else {View on GitHub (pinned to beaa561337)