{"record":{"id":"24a25f01201e7d84","repo":"fish2018/pansou","slug":"s-http-d-url-s","errorCode":null,"errorMessage":"[%s] HTTP状态码异常: %d url=%s","messagePattern":"\\[(.+?)\\] HTTP状态码异常: (.+?) url=(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/qiwei/qiwei.go","lineNumber":628,"sourceCode":"\nfunc (p *QiweiPlugin) fetchBody(client *http.Client, requestURL, referer string, timeout time.Duration) (string, error) {\n\tctx, cancel := context.WithTimeout(context.Background(), timeout)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"[%s] 创建请求失败: %w\", p.Name(), err)\n\t}\n\tp.setHeaders(req, referer)\n\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn \"\", fmt.Errorf(\"[%s] HTTP状态码异常: %d url=%s\", p.Name(), resp.StatusCode, requestURL)\n\t}\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"[%s] 读取响应失败: %w\", p.Name(), err)\n\t}\n\n\treturn normalizeResponseBody(string(body)), nil\n}\n\nfunc (p *QiweiPlugin) doRequestWithRetry(req *http.Request, client *http.Client) (*http.Response, error) {\n\tconst maxRetries = 3\n\tvar lastErr error\n\n\tfor i := 0; i < maxRetries; i++ {\n\t\tif i > 0 {\n\t\t\ttime.Sleep(time.Duration(1<<uint(i-1)) * 200 * time.Millisecond)\n\t\t}","sourceCodeStart":610,"sourceCodeEnd":646,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/qiwei/qiwei.go#L610-L646","documentation":"fetchBody requires HTTP 200 for every request. Any other status (403 from the anti-bot, 404 for a moved detail page, 5xx, redirects that end non-200) aborts with this error, which embeds the status code and the requested URL.","triggerScenarios":"resp.StatusCode != http.StatusOK after doRequestWithRetry in fetchBody, invoked by searchSuggest, getDetailInfo, or solveVerification — e.g. the site returns 403/429 when anti-bot protection triggers, or 404 for a dead detail URL.","commonSituations":"Site blocks the client's IP or user-agent with 403/429; detail page removed (404); origin 5xx during deploys; missing cookies so the anti-bot gate returns non-200.","solutions":["Log the wrapped url= field to identify which request failed and inspect it with curl","Check for 403/429 — back off, rotate user-agent/IP, or ensure the cookie jar carries prior session cookies","Handle 404 by refreshing the source URL list; the page is gone","Retry later on 5xx; getDetailInfo already tries alternate candidate URLs"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-check availability of a detail URL before full processing\nresp, err := client.Head(detailURL)\nif err != nil || resp.StatusCode != 200 {\n    log.Printf(\"url %s unavailable (status=%v)\", detailURL, statusOrErr(resp, err))\n}","typeGuard":null,"tryCatchPattern":"info, err := plugin.GetDetailInfo(ctx, url)\nif err != nil {\n    var statusErr interface{ Error() string }\n    if strings.Contains(err.Error(), \"HTTP状态码异常\") {\n        if strings.Contains(err.Error(), \" 403 \") || strings.Contains(err.Error(), \" 429 \") {\n            time.Sleep(rateLimitBackoff) // blocked/rate-limited\n        } else if strings.Contains(err.Error(), \" 404 \") {\n            return ErrPageGone // do not retry\n        }\n    }\n}","preventionTips":["Branch on the status code embedded in the message: 403/429 => back off, 404 => drop the URL, 5xx => retry later","Use a realistic User-Agent and keep the cookie jar so anti-bot gates pass","Respect the site's rate limits; getDetailInfo already alternates candidate URLs on failure"],"tags":["http","status-code","scraping","rate-limit"],"backgroundTag":"http-non-200-response","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}