fish2018/pansou · error

[ ] 解析搜索页面失败

Error message

[%s] 解析搜索页面失败: %w

What it means

Wrapped parse error in huban's searchAtBase (plugin/huban/huban.go:275): the search page returned 200 but goquery could not parse it into a document, typically because the body was an anti-bot or error page rather than search HTML. Content-shape failure, not network.

Solutions

  1. Retry the request — the body read failure is often transient network corruption
  2. Verify the response Content-Encoding/Content-Type matches what goquery expects (HTML)
  3. Check whether the site is returning a challenge/blocked page instead of search results
  4. Log the underlying wrapped error (err) for the root cause
  5. Ensure resp.Body is fully consumed only once and not already closed

Example fix

// before
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
	return nil, fmt.Errorf("[%s] 解析搜索页面失败: %w", p.Name(), err)
}
// after
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
	return nil, fmt.Errorf("[%s] 解析搜索页面失败: %w", p.Name(), err)
}
if doc.Find(".module-search-item").Length() == 0 {
	return nil, fmt.Errorf("[%s] 页面无搜索结果,可能被拦截", p.Name())
}
Defensive patterns

Strategy: try-catch

Type guard

func isParseError(err error) bool {
	return err != nil && strings.Contains(err.Error(), "解析搜索页面失败")
}

Try / catch

results, err := plugin.Search(keyword)
if isParseError(err) {
	log.Printf("search page unparseable, retrying once: %v", err)
	results, err = plugin.Search(keyword)
}
if err != nil { return nil, err }

Prevention

When it happens

Trigger: goquery.NewDocumentFromReader(resp.Body) returns a non-nil error during searchAtBase — typically truncated/gzip-corrupted body or an I/O error while reading the response stream.

Common situations: 镜像站返回压缩/二进制内容;站点改版输出格式变化。

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/efc66846c1bbce1e. Report an issue: GitHub.

Appendix: source

Thrown at plugin/huban/huban.go:275

	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
	req.Header.Set("Connection", "keep-alive")
	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 *HubanAsyncPlugin) parseSearchItem(s *goquery.Selection, keyword string) model.SearchResult {
	result := model.SearchResult{}

View on GitHub (pinned to beaa561337)