fish2018/pansou · error
[ ] 搜索请求返回状态码
Error message
[%s] 搜索请求返回状态码: %d
What it means
This error indicates zhizhen's searchAtBase received an HTTP response whose status code was not 200 after a successful (retried) request. Unlike the yunsou plugin, the retry loop here treats any completed response as success, so non-200 statuses are checked and rejected explicitly right after. The plugin could not get a usable search page from that mirror.
Solutions
- Log the actual status code (it's included in the message) and the response body snippet.
- If 403/429, update User-Agent/Referer headers or add delays between requests.
- If 301/302 to a new domain, update the plugin's base URL list.
- Check the mirror's health manually with curl -I.
- Let searchImpl fall back to another base URL (its normal behavior for this case).
Example fix
// before
if resp.StatusCode != 200 {
return nil, fmt.Errorf("[%s] 搜索请求返回状态码: %d", p.Name(), resp.StatusCode)
}
// after
if resp.StatusCode != 200 {
body, _ := io.ReadAll(io.LimitReader(resp.Body, 256))
return nil, fmt.Errorf("[%s] 搜索请求返回状态码: %d, body: %q", p.Name(), resp.StatusCode, body)
} Defensive patterns
Strategy: fallback
Validate before calling
resp, err := http.Get(strings.TrimRight(baseURL, "/") + "/")
if err == nil && resp.StatusCode == 301 {
// mirror moved — resolve new location before searching
} Try / catch
results, err := searchAtBase(client, baseURL, keyword)
if err != nil && strings.Contains(err.Error(), "状态码") {
return searchAtBase(client, nextBaseURL, keyword) // try mirror fallback
} Prevention
- Log non-200 status codes with body snippets
- Update mirror list when domains redirect elsewhere
- Handle 403/429 by rotating headers or adding delay
- Disable auto-redirect or verify redirect targets
When it happens
Trigger: resp.StatusCode != 200 immediately after doRequestWithRetry succeeds — typically 301/302 followed to an error page, 403 WAF block, 429 rate limit, or 5xx from the mirror.
Common situations: Anti-bot protection on the mirror, mirror serving a maintenance page, domain redirecting to a parking/advert page after the site migrated, or rate limiting under concurrent searches.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/fd201f310bcdbf04.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/zhizhen/zhizhen.go:223
// 4. 设置完整的请求头(避免反爬虫)
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
req.Header.Set("Connection", "keep-alive")
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)
}
})
View on GitHub (pinned to beaa561337)