{"record":{"id":"a89f2e0211cee428","repo":"fish2018/pansou","slug":"s-d-a89f2e","errorCode":null,"errorMessage":"[%s] 请求返回状态码: %d","messagePattern":"\\[(.+?)\\] 请求返回状态码: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/pianku/pianku.go","lineNumber":147,"sourceCode":"\t// 创建请求\n\treq, err := http.NewRequestWithContext(ctx, \"GET\", searchURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 创建请求失败: %w\", p.Name(), err)\n\t}\n\t\n\t// 设置请求头\n\tp.setRequestHeaders(req)\n\t\n\t// 发送HTTP请求（带重试机制）\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err)\n\t}\n\tdefer resp.Body.Close()\n\t\n\t// 检查状态码\n\tif resp.StatusCode != 200 {\n\t\treturn nil, fmt.Errorf(\"[%s] 请求返回状态码: %d\", p.Name(), resp.StatusCode)\n\t}\n\t\n\t// 解析HTML\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] HTML解析失败: %w\", p.Name(), err)\n\t}\n\t\n\t// 提取搜索结果基本信息\n\tsearchResults := p.extractSearchResults(doc)\n\t\n\t// 为每个搜索结果获取详情页的下载链接\n\tvar finalResults []model.SearchResult\n\tfor _, result := range searchResults {\n\t\t// 获取详情页链接\n\t\tif len(result.Links) == 0 {\n\t\t\tcontinue\n\t\t}","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/pianku/pianku.go#L129-L165","documentation":"Status error in pianku's searchImpl (plugin/pianku/pianku.go:147): the search page responded with a non-200 status after retries. The server was reachable but refused the request, so HTML parsing is skipped.","triggerScenarios":"GET of the pianku search page (after successful transport) returns e.g. 403 (Cloudflare/WAF), 429 (too many requests), 404 (endpoint moved), or 500.","commonSituations":"请求头特征被拦截；站点临时不可用。","solutions":["Log the status code; for 403/503 check whether setRequestHeaders is sending a valid User-Agent and cookies","Add backoff on 429 and reduce request frequency","Verify the search URL still exists (404 means the site moved it)","Use cloudscraper/proxy if the site enabled Cloudflare protection"],"exampleFix":"// before\nif resp.StatusCode != 200 {\n    return nil, fmt.Errorf(\"[%s] 请求返回状态码: %d\", p.Name(), resp.StatusCode)\n}\n// after\nif resp.StatusCode != 200 {\n    if resp.StatusCode == 429 {\n        time.Sleep(2*time.Second)\n        return p.searchImpl(client, keyword, ext)\n    }\n    return nil, fmt.Errorf(\"[%s] 请求返回状态码: %d\", p.Name(), resp.StatusCode)\n}","handlingStrategy":"retry","validationCode":"if req.Header.Get(\"User-Agent\") == \"\" {\n    return fmt.Errorf(\"missing User-Agent, expect anti-bot 403\")\n}","typeGuard":null,"tryCatchPattern":"results, err := plugin.Search(keyword, ext)\nif err != nil {\n    if strings.Contains(err.Error(), \"请求返回状态码: 429\") {\n        time.Sleep(backoff) // retry\n    } else if strings.Contains(err.Error(), \"请求返回状态码: 403\") {\n        // refresh cookies/User-Agent or enable proxy\n    }\n}","preventionTips":["Always send a realistic User-Agent and cookies via setRequestHeaders","Back off on 429 instead of hammering","Smoke-test the endpoint when its protection changes"],"tags":["go","http","scraping","status-code","anti-bot"],"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"}