fish2018/pansou · error
[ ] 解析HTML失败
Error message
[%s] 解析HTML失败: %w
What it means
Returned by doSearch in the aikanzy plugin when goquery.NewDocumentFromReader fails to parse the HTTP response body as HTML. This is rare — it occurs only when reading the body fails (I/O error) or the response body is not valid parseable content (e.g. binary data, compressed/garbled encoding).
Solutions
- Check that the http.Client Transport isn't forcing an Accept-Encoding the client can't decode; let net/http handle gzip automatically.
- Read the body into memory first (io.ReadAll) and inspect it to confirm it is HTML before parsing.
- Verify the connection isn't truncated (check for partial results; retry on read errors).
- If the site serves non-HTML challenge pages, update headers/cookies to pass anti-bot checks.
Example fix
// before
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return nil, fmt.Errorf("[%s] 解析HTML失败: %w", p.Name(), err)
}
// after
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("[%s] 读取响应体失败: %w", p.Name(), err)
}
doc, err := goquery.NewDocumentFromReader(bytes.NewReader(bodyBytes))
if err != nil {
return nil, fmt.Errorf("[%s] 解析HTML失败 (前100字节: %q): %w", p.Name(), bodyBytes[:min(100, len(bodyBytes))], err)
} Defensive patterns
Strategy: try-catch
Validate before calling
ct := resp.Header.Get("Content-Type")
if !strings.Contains(ct, "text/html") {
return fmt.Errorf("unexpected content type: %s", ct)
} Try / catch
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
// retry once; if it persists, dump the body for inspection
raw, rerr := io.ReadAll(resp.Body)
if rerr == nil {
log.Printf("unparseable body head: %q", raw[:min(200, len(raw))])
}
return err
} Prevention
- Let net/http handle gzip/deflate transparently; don't set Accept-Encoding manually unless you decode it yourself.
- Verify Content-Type is text/html before parsing.
- Read the full body with a size limit and check for truncation.
- Treat CAPTCHA/challenge responses as an anti-bot signal, not a parse bug.
When it happens
Trigger: After a 200 response, goquery.NewDocumentFromReader(resp.Body) returns an error because the body stream failed mid-read or the content is not HTML (e.g. a compressed body with mismatched Content-Encoding, or a challenge page served as non-HTML).
Common situations: Server returns gzip/brotli content that http.Client didn't transparently decompress (custom Transport missing Accept-Encoding handling); truncated response due to connection reset mid-body; site serves a CAPTCHA/JS-challenge page with unexpected encoding.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/155f5273db287466.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/aikanzy/aikanzy.go:174
req.Header.Set("Upgrade-Insecure-Requests", "1")
req.Header.Set("Cache-Control", "max-age=0")
// 使用带重试的请求方法发送HTTP请求
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return nil, fmt.Errorf("[%s] 请求搜索页面失败: %w", p.Name(), err)
}
defer resp.Body.Close()
// 检查状态码
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("[%s] 请求搜索页面失败,状态码: %d", p.Name(), resp.StatusCode)
}
// 使用goquery解析HTML
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return nil, fmt.Errorf("[%s] 解析HTML失败: %w", p.Name(), err)
}
// 解析搜索结果列表
articleItems := p.parseArticleList(doc)
if len(articleItems) == 0 {
return []model.SearchResult{}, nil
}
// 并发抓取详情页获取网盘链接
results := p.fetchDetailsWithLinks(articleItems, client, keyword)
// 使用过滤功能过滤结果
filteredResults := plugin.FilterResultsByKeyword(results, keyword)
return filteredResults, nil
}
// ArticleItem 文章基本信息View on GitHub (pinned to beaa561337)