{"record":{"id":"ee47ae40c18f3329","repo":"fish2018/pansou","slug":"w-ee47ae","errorCode":null,"errorMessage":"解析验证响应失败: %w","messagePattern":"解析验证响应失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/gying/gying.go","lineNumber":1888,"sourceCode":"\t\treturn fmt.Errorf(\"提交验证失败: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif DebugLog {\n\t\tfmt.Printf(\"[Gying] Challenge提交完成: url=%s status=%d\\n\", requestURL, resp.StatusCode)\n\t}\n\n\trespBody, err := ioutil.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"读取验证响应失败: %w\", err)\n\t}\n\tif isBotChallengePage(respBody) {\n\t\treturn fmt.Errorf(\"机器人验证出现循环\")\n\t}\n\n\tvar verifyResp challengeVerifyResponse\n\tif err := json.Unmarshal(respBody, &verifyResp); err != nil {\n\t\treturn fmt.Errorf(\"解析验证响应失败: %w\", err)\n\t}\n\tif !verifyResp.Success {\n\t\tif verifyResp.Msg != \"\" {\n\t\t\treturn fmt.Errorf(\"机器人验证失败: %s\", verifyResp.Msg)\n\t\t}\n\t\treturn fmt.Errorf(\"机器人验证失败\")\n\t}\n\n\tif DebugLog {\n\t\tfmt.Printf(\"[Gying] Challenge验证成功: url=%s\\n\", requestURL)\n\t}\n\n\treturn nil\n}\n\nfunc (p *GyingPlugin) requestWithChallengeRetry(scraper *cloudscraper.Scraper, method, requestURL, contentType, requestBody string) ([]byte, int, http.Header, error) {\n\tfor attempt := 0; attempt < 2; attempt++ {\n\t\tvar (","sourceCodeStart":1870,"sourceCodeEnd":1906,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/gying/gying.go#L1870-L1906","documentation":"Wrapped decode error in gying's challenge verification submission (plugin/gying/gying.go:1888): the verification endpoint answered 200 with a body that is not the expected challengeVerifyResponse JSON — typically another challenge page or an HTML error.","triggerScenarios":"submitChallengeVerification receives a 200 response whose body is not valid JSON matching challengeVerifyResponse (e.g. an HTML error page with a 200 status).","commonSituations":"提交后触发新一轮反爬页面；验证接口结构变更。","solutions":["Log a snippet of respBody to see what was actually returned.","Check resp.StatusCode alongside the body; non-200 usually means an HTML error page.","Update cloudscraper / challenge parsing if the site changed its verify endpoint response.","Retry; transient HTML interstitials can masquerade as parse failures."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if !json.Valid(respBody) { return fmt.Errorf(\"non-JSON response (status=%d)\", resp.StatusCode) }","typeGuard":"var probe map[string]any; if err := json.Unmarshal(respBody, &probe); err != nil || probe[\"success\"] == nil { /* treat as HTML/error page */ }","tryCatchPattern":"if err != nil { if strings.Contains(err.Error(), \"解析验证响应失败\") { logBodySnippet(respBody); checkStatusCode(); } }","preventionTips":["Always log the first bytes of the body on parse failure","Check HTTP status alongside JSON expectations","Handle CDN/WAF HTML pages explicitly","Pin and update the scraping library when sites change APIs"],"tags":["json","parsing","cloudscraper","challenge-verification"],"backgroundTag":"json-unmarshal-failed","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"}