{"record":{"id":"493ec7c65eb5ed72","repo":"fish2018/pansou","slug":"s-shttp-d","errorCode":null,"errorMessage":"[%s] %sHTTP状态错误: %d","messagePattern":"\\[(.+?)\\] (.+?)HTTP状态错误: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/diduan/diduan.go","lineNumber":198,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 解析搜索结果HTML失败: %w\", p.Name(), err)\n\t}\n\n\treturn p.parseSearchResults(doc)\n}\n\n// getPage 串行化 cloudscraper 调用，避免其 stealth 计数器并发竞争。\nfunc (p *DiduanPlugin) getPage(rawURL string) (*http.Response, error) {\n\tp.scraperMu.Lock()\n\tdefer p.scraperMu.Unlock()\n\treturn p.scraper.Get(rawURL)\n}\n\nfunc (p *DiduanPlugin) httpStatusError(action string, resp *http.Response) error {\n\tif strings.EqualFold(resp.Header.Get(\"cf-mitigated\"), \"challenge\") {\n\t\treturn fmt.Errorf(\"[%s] %s触发 Cloudflare Managed Challenge (HTTP %d)\", p.Name(), action, resp.StatusCode)\n\t}\n\treturn fmt.Errorf(\"[%s] %sHTTP状态错误: %d\", p.Name(), action, resp.StatusCode)\n}\n\n// parseSearchResults 解析搜索结果HTML\nfunc (p *DiduanPlugin) parseSearchResults(doc *goquery.Document) ([]model.SearchResult, error) {\n\tvar results []model.SearchResult\n\n\t// ddys.io 当前页面使用 movie-card；影视搜索区的第一个 h2 下才是搜索结果，\n\t// 后面的 movie-card 是推荐内容，不能一并请求详情页。\n\tvar cards *goquery.Selection\n\tdoc.Find(\"h2\").EachWithBreak(func(_ int, heading *goquery.Selection) bool {\n\t\tif strings.HasPrefix(strings.TrimSpace(heading.Text()), \"影视\") {\n\t\t\tcards = heading.Parent().Parent().Find(\".movie-card\")\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\tif cards == nil || cards.Length() == 0 {\n\t\t// 兼容旧模板：仅扫描文章列表。","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/diduan/diduan.go#L180-L216","documentation":"The fallback branch of httpStatusError: when a response has a non-200 status and the cf-mitigated header does not indicate a challenge, the plugin returns this generic HTTP status error naming the action and code. It is the Diduan plugin's standard non-OK HTTP response error.","triggerScenarios":"executeSearch (search page) or fetchDetailPageLinks (detail pages) receives resp.StatusCode != 200 without a Cloudflare challenge header — e.g. 404 after an endpoint/URL change, 403 from IP bans, 429 rate limiting, 5xx server errors.","commonSituations":"Site restructured so SearchPath/detail URLs 404; rate limiting (429) from aggressive scraping; WAF IP bans (403); temporary upstream 5xx outages.","solutions":["Log the status code and act on it: 404 means check BaseURL/SearchPath against the live site; 429 means slow down; 403 means IP blocked.","Add exponential backoff for 429/5xx responses.","Verify the constructed URL is correct (keyword escaping, path format).","Rotate proxies or egress IPs if 403 persists."],"exampleFix":"// before\nif err != nil { return err }\n// after\nif err != nil {\n    var httpErr *HTTPStatusError\n    if errors.As(err, &httpErr) && httpErr.StatusCode == 429 {\n        time.Sleep(time.Minute) // honor rate limit\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil {\n    var httpErr *HTTPStatusError\n    if errors.As(err, &httpErr) {\n        switch httpErr.StatusCode {\n        case 429:\n            time.Sleep(time.Minute)\n        case 404:\n            return fmt.Errorf(\"endpoint moved; refresh URL config: %w\", err)\n        }\n    }\n    return err\n}","preventionTips":["Handle 429 with backoff and 404 with URL-config refresh explicitly.","Monitor status-code distribution per target site.","Rotate proxies when persistent 403s appear.","Validate constructed URLs against the live site when endpoints change."],"tags":["http","status-code","http-non-200","go"],"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"}