fish2018/pansou · error

[ ] 请求返回状态码

Error message

[%s] 请求返回状态码: %d

What it means

Status error in pianku's searchImpl (plugin/pianku/pianku.go:147): the search page responded with a non-200 status after retries. The server was reachable but refused the request, so HTML parsing is skipped.

Solutions

  1. Log the status code; for 403/503 check whether setRequestHeaders is sending a valid User-Agent and cookies
  2. Add backoff on 429 and reduce request frequency
  3. Verify the search URL still exists (404 means the site moved it)
  4. Use cloudscraper/proxy if the site enabled Cloudflare protection

Example fix

// before
if resp.StatusCode != 200 {
    return nil, fmt.Errorf("[%s] 请求返回状态码: %d", p.Name(), resp.StatusCode)
}
// after
if resp.StatusCode != 200 {
    if resp.StatusCode == 429 {
        time.Sleep(2*time.Second)
        return p.searchImpl(client, keyword, ext)
    }
    return nil, fmt.Errorf("[%s] 请求返回状态码: %d", p.Name(), resp.StatusCode)
}
Defensive patterns

Strategy: retry

Validate before calling

if req.Header.Get("User-Agent") == "" {
    return fmt.Errorf("missing User-Agent, expect anti-bot 403")
}

Try / catch

results, err := plugin.Search(keyword, ext)
if err != nil {
    if strings.Contains(err.Error(), "请求返回状态码: 429") {
        time.Sleep(backoff) // retry
    } else if strings.Contains(err.Error(), "请求返回状态码: 403") {
        // refresh cookies/User-Agent or enable proxy
    }
}

Prevention

When it happens

Trigger: GET of the pianku search page (after successful transport) returns e.g. 403 (Cloudflare/WAF), 429 (too many requests), 404 (endpoint moved), or 500.

Common situations: 请求头特征被拦截;站点临时不可用。

Related errors


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

Appendix: source

Thrown at plugin/pianku/pianku.go:147

	// 创建请求
	req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
	if err != nil {
		return nil, fmt.Errorf("[%s] 创建请求失败: %w", p.Name(), err)
	}
	
	// 设置请求头
	p.setRequestHeaders(req)
	
	// 发送HTTP请求(带重试机制)
	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)
	}
	
	// 解析HTML
	doc, err := goquery.NewDocumentFromReader(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("[%s] HTML解析失败: %w", p.Name(), err)
	}
	
	// 提取搜索结果基本信息
	searchResults := p.extractSearchResults(doc)
	
	// 为每个搜索结果获取详情页的下载链接
	var finalResults []model.SearchResult
	for _, result := range searchResults {
		// 获取详情页链接
		if len(result.Links) == 0 {
			continue
		}

View on GitHub (pinned to beaa561337)