fish2018/pansou · error
[ ] 详情页返回状态码
Error message
[%s] 详情页返回状态码: %d
What it means
This error is raised by fetchDetailData in the Mizixing plugin when the detail page HTTP response does not return status 200. The plugin aborts parsing because the body likely does not contain the expected HTML article structure. It wraps the plugin name and the actual status code so the caller knows which upstream response failed.
Solutions
- Log the status code and check the target site availability in a browser or with curl to identify whether it's 4xx (URL/blocking) or 5xx (server side)
- Ensure a realistic User-Agent/browser-like header set is sent to avoid 403 anti-bot responses
- Add or increase retry with backoff for transient 5xx/429 responses before failing
- Verify the detail URL is built from a valid, current item ID returned by search
- Handle non-200 gracefully upstream (skip the item) instead of crashing the whole search run
Example fix
// before
resp, err := p.doRequest(req)
if resp.StatusCode != http.StatusOK {
return detailData{}, fmt.Errorf("[%s] 详情页返回状态码: %d", p.Name(), resp.StatusCode)
}
// after
resp, err := p.doRequest(req)
if err != nil {
return detailData{}, err
}
if resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= 500 {
if r, rerr := p.doRequestWithRetry(req); rerr == nil {
resp = r
}
}
if resp.StatusCode != http.StatusOK {
return detailData{}, fmt.Errorf("[%s] 详情页返回状态码: %d", p.Name(), resp.StatusCode)
} Defensive patterns
Strategy: retry
Validate before calling
// pre-check before calling search
detailURL := buildDetailURL(id)
if u, err := url.Parse(detailURL); err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid detail url: %s", detailURL)
} Try / catch
detail, err := p.fetchDetailData(id)
if err != nil {
var httpErr interface{ Unwrap() error }
log.Printf("detail fetch failed, skipping item: %v", err)
return fallbackResult(id) // degrade gracefully
} Prevention
- Send full browser-like headers to avoid 403 anti-bot responses
- Retry transient statuses (429, 5xx) with exponential backoff
- Validate detail URLs before requesting
- Check target site health before bulk scraping runs
When it happens
Trigger: Triggered whenever an HTTP GET to the Mizixing detail page completes but resp.StatusCode != http.StatusOK (e.g. 403 from anti-bot protection, 404 for a stale detail URL, 429 rate limiting, 5xx server errors).
Common situations: Site temporarily down or under maintenance; IP blocked by WAF/CDN; the detail URL was constructed from an outdated or invalid item ID; heavy scraping triggering rate limits.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/e0fc507cde9a3ca1.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/mizixing/mizixing.go:254
func (p *MizixingPlugin) fetchDetailData(client *http.Client, detailURL string) (detailData, error) {
ctx, cancel := context.WithTimeout(context.Background(), detailTimeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, detailURL, nil)
if err != nil {
return detailData{}, fmt.Errorf("[%s] 创建详情页请求失败: %w", p.Name(), err)
}
setHTMLHeaders(req, detailURL)
resp, err := p.doRequestWithRetry(req, client, maxRequestRetries)
if err != nil {
return detailData{}, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return detailData{}, fmt.Errorf("[%s] 详情页返回状态码: %d", p.Name(), resp.StatusCode)
}
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return detailData{}, fmt.Errorf("[%s] 解析详情页失败: %w", p.Name(), err)
}
content := doc.Find("article.article-content")
if content.Length() == 0 {
content = doc.Find(".article-content")
}
if content.Length() == 0 {
content = doc.Find(".entry-content")
}
if content.Length() == 0 {
content = doc.Selection
}
View on GitHub (pinned to beaa561337)