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

  1. Read the body with io.ReadAll first and log its length/snippet to diagnose.
  2. Re-run against another base URL — searchImpl's mirror fallback handles transient corruption.
  3. Ensure the transport handles gzip (DefaultTransport does when Accept-Encoding is unset).
  4. Retry the request; truncation is usually transient.
  5. 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

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)