{"record":{"id":"49879c918b673190","repo":"fish2018/pansou","slug":"html-w","errorCode":null,"errorMessage":"解析HTML失败: %w","messagePattern":"解析HTML失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/hdr4k/hdr4k.go","lineNumber":161,"sourceCode":"\t\treturn nil, fmt.Errorf(\"创建请求失败: %w\", err)\n\t}\n\t\n\t// 设置请求头\n\treq.Header.Set(\"User-Agent\", getRandomUA())\n\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\treq.Header.Set(\"Referer\", \"https://www.4khdr.cn/\")\n\t\n\t// 发送请求（带重试）\n\tresp, err := p.doRequestWithRetry(client, req, MaxRetries)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"请求失败: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\t\n\t// 解析HTML\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"解析HTML失败: %w\", err)\n\t}\n\t\n\t// 提取搜索结果\n\tvar wg sync.WaitGroup\n\tresultChan := make(chan model.SearchResult, 20)\n\terrorChan := make(chan error, 20)\n\t\n\t// 创建信号量控制并发数\n\tsemaphore := make(chan struct{}, MaxConcurrency)\n\t\n\t// 预先收集所有需要处理的项\n\tvar items []*goquery.Selection\n\t\n\t// 将关键词转为小写，用于不区分大小写的比较\n\tlowerKeyword := strings.ToLower(keyword)\n\t\n\t// 将关键词按空格分割，用于支持多关键词搜索\n\tkeywords := strings.Fields(lowerKeyword)","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/hdr4k/hdr4k.go#L143-L179","documentation":"The hdr4k plugin wraps any error from goquery.NewDocumentFromReader(resp.Body) — which reads the whole search-results HTML response — with this message. goquery only fails here if the underlying io.ReadAll of resp.Body fails, meaning the response body could not be read. It is a wrapper around a low-level network/IO failure that happened while draining the HTTP response.","triggerScenarios":"Called in doSearch after a successful doRequestWithRetry; it triggers when reading resp.Body fails, e.g. the connection was reset or timed out mid-body, the server closed the connection early, or a proxy interrupted the transfer.","commonSituations":"Unstable connections to www.4khdr.cn, server-side connection drops on large search pages, VPN/proxy interference, or firewalls that cut long-lived response streams.","solutions":["Retry the search request; transient body-read failures usually succeed on a second attempt (the plugin already retries the request, but not the body read).","Check network connectivity/proxy settings between the host and www.4khdr.cn.","Inspect the wrapped %w error to identify the exact underlying IO failure.","Verify the site is reachable in a browser and not blocking your IP/rate-limiting you."],"exampleFix":"// before\nresp, err := p.doRequestWithRetry(client, req, MaxRetries)\nif err != nil { return nil, err }\ndoc, err := goquery.NewDocumentFromReader(resp.Body)\nif err != nil {\n    return nil, fmt.Errorf(\"解析HTML失败: %w\", err)\n}\n// after\nresp, err := p.doRequestWithRetry(client, req, MaxRetries)\nif err != nil { return nil, err }\nbody, readErr := io.ReadAll(resp.Body)\nresp.Body.Close()\nif readErr != nil {\n    return nil, fmt.Errorf(\"读取响应体失败(可重试): %w\", readErr)\n}\ndoc, err := goquery.NewDocumentFromReader(bytes.NewReader(body))","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"results, err := plugin.Search(keyword, ext)\nif err != nil {\n    var transient = strings.Contains(err.Error(), \"解析HTML失败\")\n    if transient {\n        time.Sleep(2 * time.Second)\n        results, err = plugin.Search(keyword, ext) // one manual retry\n    }\n    if err != nil {\n        log.Printf(\"hdr4k search failed: %v\", err)\n        return fallbackResults\n    }\n}","preventionTips":["Run searches from a host with stable connectivity to www.4khdr.cn","Wrap body reads so transient IO failures are retried independently","Always inspect the wrapped %w cause, not just the outer message","Set reasonable client timeouts so connections aren't cut mid-body"],"tags":["network","http","html-parsing","go"],"backgroundTag":"network-request-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"}