{"record":{"id":"d903d8300c828e4c","repo":"fish2018/pansou","slug":"s-api-api-v","errorCode":null,"errorMessage":"[%s] API 失败且网页搜索没有有效资源 (API: %v)","messagePattern":"\\[(.+?)\\] API 失败且网页搜索没有有效资源 \\(API: (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/feikuai/feikuai.go","lineNumber":256,"sourceCode":"\t\t\ttitle = strings.TrimSpace(item.Find(\"h4\").Text())\n\t\t}\n\t\tcontent := strings.TrimSpace(item.Find(\".ext-meta\").Text())\n\t\tadd(href, title, content, parseFeikuaiWebTime(content))\n\t})\n\tdoc.Find(\"#panel-bm .bm-item a.module-row-text[href]\").Each(func(_ int, item *goquery.Selection) {\n\t\tif len(results) >= 100 {\n\t\t\treturn\n\t\t}\n\t\thref := item.AttrOr(\"href\", \"\")\n\t\ttitle := strings.TrimSpace(item.AttrOr(\"title\", \"\"))\n\t\tif title == \"\" {\n\t\t\ttitle = strings.TrimSpace(item.Find(\".bm-file\").Text())\n\t\t}\n\t\tcontent := strings.TrimSpace(item.Find(\".ext-meta\").Text())\n\t\tadd(href, title, content, parseFeikuaiWebTime(content))\n\t})\n\tif len(results) == 0 {\n\t\treturn nil, fmt.Errorf(\"[%s] API 失败且网页搜索没有有效资源 (API: %v)\", p.Name(), apiErr)\n\t}\n\treturn plugin.FilterResultsByKeyword(results, keyword), nil\n}\n\nfunc extractWebPassword(linkURL, content string) string {\n\tif parsed, err := url.Parse(linkURL); err == nil {\n\t\tif pwd := parsed.Query().Get(\"pwd\"); pwd != \"\" {\n\t\t\treturn pwd\n\t\t}\n\t}\n\tif match := regexp.MustCompile(`(?i)(?:提取码|密码|pwd)[:：]?\\s*([a-z0-9]{4})`).FindStringSubmatch(content); len(match) > 1 {\n\t\treturn match[1]\n\t}\n\treturn \"\"\n}\n\nfunc parseFeikuaiWebTime(text string) time.Time {\n\tmatch := regexp.MustCompile(`\\d{4}-\\d{2}-\\d{2}(?:[T ]\\d{2}:\\d{2}:\\d{2})?`).FindString(text)","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/feikuai/feikuai.go#L238-L274","documentation":"After the primary API call failed and the plugin fell back to scraping the web search page, zero parseable results were found. The plugin wraps both failures into this combined error because it has no usable data to return.","triggerScenarios":"searchWeb: the API errored (apiErr non-nil) AND the DOM selector pass over the fallback HTML matched no result items (len(results) == 0).","commonSituations":"Site markup changed so the CSS selectors (.bm-file, .ext-meta, etc.) no longer match; the site served a captcha or empty results page; keyword genuinely has no results but is wrapped with the API error.","solutions":["Inspect the fallback page HTML and update the plugin's CSS selectors to the current markup.","Check whether the site serves a captcha/anti-bot page and add proper headers/cookies.","Retry later or with a different keyword to distinguish 'no results' from a broken scraper.","Fix the primary API error (apiErr) so the fallback is not required."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// probe the fallback page and count expected selector matches\nn := doc.Find(\"div.result-item\").Length()\nif n == 0 {\n    log.Println(\"fallback page returned no items; markup may have changed\")\n}","typeGuard":null,"tryCatchPattern":"results, err := searchImpl(keyword)\nif err != nil {\n    if strings.Contains(err.Error(), \"没有有效资源\") {\n        log.Printf(\"no results and API down: %v\", err)\n        return emptyOrCachedResults()\n    }\n    return err\n}","preventionTips":["Pin selector assumptions with a small integration test against live markup","Distinguish 'genuinely no results' from 'scraping broke' before wrapping the error","Monitor the API path so the fallback is not the normal code path","Add headers/cookies to avoid captcha pages returning zero items"],"tags":["web-scraping","empty-results","go","css-selectors"],"backgroundTag":"empty-result-set","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"}