{"record":{"id":"1a9ebf0b084df51b","repo":"fish2018/pansou","slug":"s-json-w-1a9ebf","errorCode":null,"errorMessage":"[%s] 解析JSON响应失败: %w","messagePattern":"\\[(.+?)\\] 解析JSON响应失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/wanou/wanou.go","lineNumber":154,"sourceCode":"\treq.Header.Set(\"Referer\", \"https://woog.nxog.eu.org/\")\n\treq.Header.Set(\"Cache-Control\", \"no-cache\")\n\t\n\t// 发送请求\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// 解析JSON响应\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 读取响应失败: %w\", p.Name(), err)\n\t}\n\t\n\tvar apiResponse WanouAPIResponse\n\tif err := json.Unmarshal(body, &apiResponse); err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 解析JSON响应失败: %w\", p.Name(), err)\n\t}\n\t\n\t// 检查API响应状态\n\tif apiResponse.Code != 1 {\n\t\treturn nil, fmt.Errorf(\"[%s] API返回错误: %s\", p.Name(), apiResponse.Msg)\n\t}\n\t\n\t// 解析搜索结果\n\tvar results []model.SearchResult\n\tfor _, item := range apiResponse.List {\n\t\tif result := p.parseAPIItem(item); result.Title != \"\" {\n\t\t\tresults = append(results, result)\n\t\t}\n\t}\n\t\n\treturn results, nil\n}\n","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/wanou/wanou.go#L136-L172","documentation":"searchImpl unmarshals the response body into WanouAPIResponse with encoding/json. If the body is not valid JSON or does not match the struct (e.g. an HTML error page or CAPTCHA page is returned), it throws '解析JSON响应失败' (failed to parse JSON response).","triggerScenarios":"The wanou endpoint returns HTML (block page, Cloudflare challenge, login page), an empty body, or JSON with fields whose types don't match WanouAPIResponse (e.g. string \"code\" vs number).","commonSituations":"Anti-bot page returned with HTTP 200; the site's API changed its response shape; the domain now serves an HTML notice; response compressed/garbled due to missing Accept-Encoding handling.","solutions":["Log the first ~200 bytes of body to see what was actually returned","Check for HTML: the mirror is likely serving an anti-bot/block page — change domain or add cookies","Update WanouAPIResponse struct to match the current API schema","Verify the endpoint URL still points at the JSON API"],"exampleFix":"// before\nif err := json.Unmarshal(body, &apiResponse); err != nil {\n    return nil, fmt.Errorf(\"[%s] 解析JSON响应失败: %w\", p.Name(), err)\n}\n// after\nif err := json.Unmarshal(body, &apiResponse); err != nil {\n    log.Debugf(\"wanou non-JSON body: %.200s\", body)\n    return nil, fmt.Errorf(\"[%s] 解析JSON响应失败(非JSON/反爬页面?): %w\", p.Name(), err)\n}","handlingStrategy":"validation","validationCode":"if !json.Valid(body) {\n    return fmt.Errorf(\"wanou returned non-JSON (likely block page): %.100s\", body)\n}","typeGuard":null,"tryCatchPattern":"var apiResponse WanouAPIResponse\nif err := json.Unmarshal(body, &apiResponse); err != nil {\n    if !json.Valid(body) {\n        return nil, fmt.Errorf(\"upstream returned HTML/block page\")\n    }\n    return nil, fmt.Errorf(\"schema mismatch: %w\", err)\n}","preventionTips":["Inspect raw bodies when the shape changes","Keep the response struct in sync with the live API","Handle compressed responses (Accept-Encoding)","Detect and rotate away from block-page-serving mirrors"],"tags":["json","parsing","api","scraping"],"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"}