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

  1. Log part of resp.Body content to confirm what was actually received.
  2. Check Content-Encoding/gzip handling; ensure the http.Client transport decompresses (DisableCompression=false).
  3. Re-run the request — transient truncation is common; rely on the existing retry wrapper.
  4. Verify the site still serves the expected HTML page and not an error/challenge page.
  5. 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

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)