fish2018/pansou · error
[ ] 访问首页失败
Error message
[%s] 访问首页失败: %w
What it means
Returned when p.doRequestWithRetry exhausts maxRequestRetries attempts to GET https://jsnoteclub.com/ without a usable response. The underlying transport error (DNS failure, TLS problem, timeout, connection refused) is wrapped via %w. All retry attempts already happened; this is the final failure.
Solutions
- Run curl -v https://jsnoteclub.com/ from the same host to isolate DNS/TLS/network problems
- Check the wrapped error for context deadline exceeded and consider increasing requestTimeout
- Verify outbound internet access and proxy environment variables (HTTP_PROXY/HTTPS_PROXY)
- Retry later — the upstream site may be temporarily down or rate-limiting your IP
- Check whether setHTMLHeaders' User-Agent is being blocked and update headers
Defensive patterns
Strategy: retry
Try / catch
key, err := plugin.fetchDataKey(client)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) {
// timeouts: increase requestTimeout or back off and retry
return backoffAndRetry()
}
return fmt.Errorf("homepage unreachable, retry later: %w", err)
} Prevention
- Run curl -v against the site from the deployment host to verify reachability
- Set requestTimeout generously (e.g. 30s) for slow upstreams
- Honor HTTP(S)_PROXY settings in restricted networks
- Add exponential backoff between the plugin's own retries and don't hammer the site
When it happens
Trigger: Every attempt of doRequestWithRetry fails: network unreachable, DNS resolution failure for jsnoteclub.com, TLS handshake error, or context deadline (requestTimeout) exceeded on each retry.
Common situations: The site is down or blocking the scraper's user agent/IP; corporate firewall or no internet access; DNS misconfiguration; requestTimeout set too low for slow networks; the site moved to a different domain (jsnoteclub.com is a small Chinese site whose uptime is not guaranteed).
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/6f41827bb8d3ce71.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/jsnoteclub/jsnoteclub.go:236
postsCache.expire = time.Now().Add(postsCacheTTL)
postsCache.key = dataKey
return posts, nil
}
func (p *JsNoteClubPlugin) fetchDataKey(client *http.Client) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://jsnoteclub.com/", nil)
if err != nil {
return "", fmt.Errorf("[%s] 创建首页请求失败: %w", p.Name(), err)
}
setHTMLHeaders(req, "https://jsnoteclub.com/")
resp, err := p.doRequestWithRetry(req, client, maxRequestRetries)
if err != nil {
return "", fmt.Errorf("[%s] 访问首页失败: %w", p.Name(), err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("[%s] 首页返回状态码: %d", p.Name(), resp.StatusCode)
}
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return "", fmt.Errorf("[%s] 解析首页失败: %w", p.Name(), err)
}
var htmlBuilder strings.Builder
doc.Find("script").Each(func(_ int, s *goquery.Selection) {
if html, err := goquery.OuterHtml(s); err == nil {
htmlBuilder.WriteString(html)
}
})View on GitHub (pinned to beaa561337)