fish2018/pansou · error
[ ] 搜索请求失败
Error message
[%s] 搜索请求失败: %w
What it means
The djgou plugin wraps any failure from its HTTP request retry loop (doRequestWithRetry) into a Chinese-language error meaning '[plugin] search request failed'. This library throws it when the site cannot be reached after all retries — DNS failure, timeout, TLS error, connection refused, or a request that never yields a response object. It preserves the underlying cause via %w.
Solutions
- Test basic reachability of the site: curl -I the SiteURL from the same host
- Check DNS/proxy environment (HTTP_PROXY/HTTPS_PROXY) and container egress rules
- Retry later or raise client/timeout settings if the site is intermittently slow
- Inspect the wrapped cause (%w) with errors.Unwrap/As(*url.Error) to identify the transport failure
Example fix
// before
items, err := p.searchImpl(keyword)
if err != nil { return err }
// after
items, err := p.searchImpl(keyword)
var urlErr *url.Error
if errors.As(err, &urlErr) && errors.Is(urlErr.Err, context.DeadlineExceeded) {
return fmt.Errorf("site timed out, retry later: %w", err)
}
return err Defensive patterns
Strategy: retry
Validate before calling
func siteReachable(siteURL string) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, siteURL, nil)
resp, err := http.DefaultClient.Do(req)
if err != nil { return err }
resp.Body.Close()
return nil
} Try / catch
items, err := p.searchImpl(keyword)
var urlErr *url.Error
if errors.As(err, &urlErr) {
log.Printf("djgou transport error: %v (timeout=%v)", urlErr.Err, errors.Is(urlErr.Err, context.DeadlineExceeded))
// schedule retry with backoff
} Prevention
- Pre-check site reachability before batch searches
- Configure proxy env vars in restricted networks
- Use generous client timeouts and exponential backoff
- Monitor DNS/IP changes of the target site
When it happens
Trigger: p.doRequestWithRetry(req, client) returns err != nil during searchImpl: all retry attempts fail at the transport level (connection refused, timeout, TLS handshake, context deadline).
Common situations: Target site (djgou) is down or blocking the host; no outbound network/DNS in the container; corporate proxy required but not configured; site IP changed; overly tight client timeout.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/dba30820a87e08b2.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/djgou/djgou.go:140
// 3. 创建请求
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
if err != nil {
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/114.0.0.0 Safari/537.36")
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;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", SiteURL)
// 5. 发送请求(带重试机制)
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
}
if resp.StatusCode != 200 {
resp.Body.Close()
return nil, fmt.Errorf("[%s] 搜索请求返回状态码: %d", p.Name(), resp.StatusCode)
}
// 6. 读取并解析搜索结果页面。部分节点先返回 BTWAF JS 跳转页。
body, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return nil, fmt.Errorf("[%s] 读取搜索页面失败: %w", p.Name(), err)
}
doc, err := goquery.NewDocumentFromReader(strings.NewReader(string(body)))
if err != nil {
return nil, fmt.Errorf("[%s] 解析搜索页面失败: %w", p.Name(), err)
}
if doc.Find("article.post-item-row").Length() == 0 {View on GitHub (pinned to beaa561337)