fish2018/pansou · error
[ ] 创建网页搜索请求失败
Error message
[%s] 创建网页搜索请求失败: %w
What it means
searchWeb is the HTML scraping fallback used when the JSON API path fails; it builds a second request to SearchWebURL and wraps any construction error in this message. As with the API path, this fires before any bytes hit the network.
Solutions
- Validate the composed searchURL with url.Parse before creating the request
- Check the SearchWebURL constant and query string composition
- Confirm url.QueryEscape is applied to all user-supplied parts
Example fix
// before
searchURL := SearchWebURL + "?wd=" + url.QueryEscape(keyword) + "&ext=1"
req, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL, nil)
// after
u, uerr := url.Parse(SearchWebURL)
if uerr != nil {
return nil, fmt.Errorf("invalid SearchWebURL %q: %w", SearchWebURL, uerr)
}
q := u.Query(); q.Set("wd", keyword); q.Set("ext", "1"); u.RawQuery = q.Encode()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(SearchWebURL)
if err != nil || u.Host == "" {
return nil, fmt.Errorf("invalid SearchWebURL %q: %w", SearchWebURL, err)
} Try / catch
results, err := plugin.Search(keyword)
if err != nil && strings.Contains(err.Error(), "创建网页搜索请求失败") {
return nil, fmt.Errorf("feikuai web fallback misconfigured: %w", err)
} Prevention
- Compose fallback URLs with url.Values, never raw string concatenation
- Keep API and web URL constants in one config validated at startup
- Re-verify both endpoints whenever the upstream site rotates domains
- Escape all keyword input via url.QueryEscape
When it happens
Trigger: http.NewRequestWithContext(ctx, http.MethodGet, SearchWebURL+"?wd="+url.QueryEscape(keyword)+"&ext=1", nil) fails — malformed URL composition or illegal characters after concatenation.
Common situations: Stale or mistyped SearchWebURL constant, keyword containing characters that break the URL even after QueryEscape (e.g. embedded control chars), domain rotation mistakes.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/ad66930ece31e0c5.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/feikuai/feikuai.go:177
results = append(results, result)
}
}
}
// 使用关键词过滤结果
return plugin.FilterResultsByKeyword(results, keyword), nil
}
// searchWebFallback parses the current server-rendered external search page.
// Feikuai's legacy JSON endpoint now responds with 403, while this page still
// exposes both disk links and magnets in stable HTML markup.
func (p *FeikuaiPlugin) searchWeb(client *http.Client, keyword string, apiErr error) ([]model.SearchResult, error) {
ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
defer cancel()
searchURL := SearchWebURL + "?wd=" + url.QueryEscape(keyword) + "&ext=1"
req, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL, nil)
if err != nil {
return nil, fmt.Errorf("[%s] 创建网页搜索请求失败: %w", p.Name(), err)
}
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/136.0.0.0 Safari/537.36")
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
req.Header.Set("Referer", "https://feikuai.in/")
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("[%s] API 失败且网页搜索请求失败: %v (API: %v)", p.Name(), err, apiErr)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("[%s] API 失败且网页搜索返回状态码 %d (API: %v)", p.Name(), resp.StatusCode, apiErr)
}
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return nil, fmt.Errorf("[%s] 网页搜索 HTML 解析失败: %w", p.Name(), err)
}
View on GitHub (pinned to beaa561337)