fish2018/pansou · error

[susu] 搜索请求返回状态码

Error message

[susu] 搜索请求返回状态码: %d

What it means

doSearch throws this when the retried search request succeeded at the transport level but the server answered with a status code other than 200 OK. The plugin treats any non-200 as a failed search and surfaces the raw status code so the caller can distinguish 403 (bot blocking), 404, 429 (rate limit), 5xx, etc. The response body is discarded without parsing.

Solutions

  1. Log/check the numeric status in the message: 403/503 often mean bot protection — verify setBrowserHeaders/getRandomUA produce plausible browser headers.
  2. If 429, back off and reduce search frequency or add rate limiting between calls.
  3. If 5xx, retry later; the site is having issues.
  4. Confirm BaseURL is current — a stale domain can return unexpected codes (e.g. parking pages).
  5. Consider extending doRequestWithRetry to also retry on 5xx/429 responses, not only transport errors.

Example fix

null
Defensive patterns

Strategy: retry

Try / catch

links, err := p.Search(query)
if err != nil {
    var statusErr interface{ Error() string }
    if strings.Contains(err.Error(), "状态码: 403") || strings.Contains(err.Error(), "状态码: 429") {
        // honor backoff / rotate headers before retry
    }
}

Prevention

When it happens

Trigger: doSearch receives resp.StatusCode != http.StatusOK after doRequestWithRetry returns a response — e.g. Cloudflare/WAF challenge page (403), rate limiting (429), maintenance (503), or a redirect to an error page.

Common situations: The site's anti-bot protection flagging the request (missing/expired cookies or UA); too-frequent searches from one IP; the site being partially down; Cloudflare returning 5xx during outages.

Related errors


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

Appendix: source

Thrown at plugin/susu/susu.go:165

	defer cancel()

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL, nil)
	if err != nil {
		return nil, fmt.Errorf("创建请求失败: %w", err)
	}

	// 设置请求头
	req.Header.Set("User-Agent", getRandomUA())
	setBrowserHeaders(req, BaseURL+"/")

	// 发送请求(带重试)
	resp, err := p.doRequestWithRetry(client, req, MaxRetries)
	if err != nil {
		return nil, fmt.Errorf("请求失败: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("[susu] 搜索请求返回状态码: %d", resp.StatusCode)
	}

	// 解析HTML
	doc, err := goquery.NewDocumentFromReader(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("解析HTML失败: %w", err)
	}

	// 提取搜索结果
	var wg sync.WaitGroup
	resultChan := make(chan model.SearchResult, 20)

	// 创建信号量控制并发数
	semaphore := make(chan struct{}, MaxConcurrency)

	// 预先收集所有需要处理的项
	var items []*goquery.Selection

View on GitHub (pinned to beaa561337)