{"record":{"id":"7a6d2755e78b467d","repo":"fish2018/pansou","slug":"s-w-7a6d27","errorCode":null,"errorMessage":"[%s] 创建详情页请求失败: %w","messagePattern":"\\[(.+?)\\] 创建详情页请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/mizixing/mizixing.go","lineNumber":243,"sourceCode":"\t})\n\n\treturn items, nil\n}\n\ntype detailData struct {\n\tlinks       []model.Link\n\tdatetime    time.Time\n\ttags        []string\n\tdescription string\n}\n\nfunc (p *MizixingPlugin) fetchDetailData(client *http.Client, detailURL string) (detailData, error) {\n\tctx, cancel := context.WithTimeout(context.Background(), detailTimeout)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, detailURL, nil)\n\tif err != nil {\n\t\treturn detailData{}, fmt.Errorf(\"[%s] 创建详情页请求失败: %w\", p.Name(), err)\n\t}\n\tsetHTMLHeaders(req, detailURL)\n\n\tresp, err := p.doRequestWithRetry(req, client, maxRequestRetries)\n\tif err != nil {\n\t\treturn detailData{}, err\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn detailData{}, fmt.Errorf(\"[%s] 详情页返回状态码: %d\", p.Name(), resp.StatusCode)\n\t}\n\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn detailData{}, fmt.Errorf(\"[%s] 解析详情页失败: %w\", p.Name(), err)\n\t}\n","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/mizixing/mizixing.go#L225-L261","documentation":"fetchDetailData failed to build the GET request for a scraped detail page URL via http.NewRequestWithContext. Since detailURL comes from parsed search-result hrefs, this almost always means an extracted link was relative, malformed, or contained invalid characters.","triggerScenarios":"searchImpl's anonymous worker extracts a detail URL from search results, then http.NewRequestWithContext rejects it — relative path without base, spaces/control chars, or empty href.","commonSituations":"Site serving protocol-relative or relative hrefs; href attributes with unescaped characters; extraction selector grabbing a non-URL attribute value.","solutions":["Resolve extracted hrefs against the base URL with resp.Request.URL.Parse or the resolve reference pattern before requesting.","Skip/normalize invalid detail URLs during extraction instead of failing.","Log the offending detailURL to confirm whether extraction or the site is at fault."],"exampleFix":"// before\ndetailURL := s.Find(\"a\").AttrOr(\"href\", \"\")\n// after\nhref := s.Find(\"a\").AttrOr(\"href\", \"\")\nu, err := url.Parse(href)\nif err != nil || u.Host == \"\" {\n    return\n}\ndetailURL := baseURL.ResolveReference(u).String()","handlingStrategy":"validation","validationCode":"u, err := url.Parse(detailHref)\nif err != nil || u.Host == \"\" {\n    return fmt.Errorf(\"invalid detail URL: %q\", detailHref)\n}\ndetailURL = baseURL.ResolveReference(u).String()","typeGuard":null,"tryCatchPattern":"data, err := fetchDetailData(client, detailURL)\nif err != nil {\n    log.Printf(\"skipping detail %q: %v\", detailURL, err)\n    return nil // skip this item, continue with others\n}","preventionTips":["Always resolve relative hrefs against the base URL before requesting.","Skip items with unusable hrefs instead of failing the whole search.","Validate scraped URLs with url.Parse during extraction."],"tags":["http","url","scraping"],"backgroundTag":"invalid-url-format","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"}