fish2018/pansou · error
[ ] 搜索请求返回状态码
Error message
[%s] 搜索请求返回状态码: %d
What it means
The huban plugin's searchAtBase method performs an HTTP search request and requires HTTP 200. Any other status code (403, 429, 500, etc.) aborts the search and returns this error, prefixed with the plugin name.
Solutions
- Log resp.StatusCode and inspect response headers/body (via a debug wrapper) to identify blocking (403/429/5xx)
- Slow down request rate / add backoff to avoid 429 rate limiting
- Rotate proxies or User-Agent to evade bot detection
- Check if the huban site is reachable in a browser; if it moved or changed protection, update the plugin's request headers or URL
- Surface the error to the user as a transient upstream failure and retry later
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, 512))
return nil, fmt.Errorf("[%s] 搜索请求返回状态码: %d, body: %s", p.Name(), resp.StatusCode, string(body))
} Defensive patterns
Strategy: retry
Validate before calling
resp, err := http.Head(searchURL)
if err != nil || resp.StatusCode != 200 {
// upstream unhealthy; skip or delay the search
} Try / catch
results, err := plugin.Search(keyword)
if err != nil {
if strings.Contains(err.Error(), "搜索请求返回状态码") {
// extract status, back off or fail over to another plugin
log.Printf("upstream non-200: %v", err)
return partialResults, nil
}
return nil, err
} Prevention
- Monitor the upstream site's availability and status codes before scraping
- Throttle request rate to avoid 429s
- Keep User-Agent and headers browser-like to reduce 403 bot blocks
- Have fallback search plugins so one non-200 upstream doesn't break the app
When it happens
Trigger: p.searchAtBase executes doRequestWithRetry (which itself retries non-200 responses) and the final response still has StatusCode != 200; e.g. the huban site returns 403 due to bot detection/Cloudflare, 429 rate limiting, or 5xx site outage.
Common situations: Target site blocking datacenter IPs or non-browser User-Agents, being rate-limited after heavy scraping, huban site temporarily down or moved behind anti-bot protection, expired cookies/TLS fingerprint rejected.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/adf9f55c0fb11fa9.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/huban/huban.go:269
return nil, fmt.Errorf("[%s] 创建请求失败: %w", p.Name(), err)
}
// 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("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)