fish2018/pansou · warning
parse html failed
Error message
parse html failed: %w
What it means
parseItems failed to parse the API-provided HTML fragment with goquery. goquery (via go-htmltransform/html parsing) rarely errors, so this usually indicates nil input or a parser-level failure; more practically it signals the fragment could not be turned into a queryable document for extracting div.layui-card results.
Solutions
- Log the fragment before parsing to confirm it contains expected markup
- Guard against empty apiResp.Data before parsing and return an empty result instead
- Update selectors if the site changed its markup (div.layui-card, a[onclick*=open_sid])
- Verify the goquery/html parser dependency versions are healthy
Example fix
// before
doc, err := goquery.NewDocumentFromReader(strings.NewReader(`<div id="yunso-root">` + fragment + `</div>`))
if err != nil {
return nil, fmt.Errorf("parse html failed: %w", err)
}
// after
if strings.TrimSpace(fragment) == "" {
return []YunsoItem{}, nil
}
doc, err := goquery.NewDocumentFromReader(strings.NewReader(`<div id="yunso-root">` + fragment + `</div>`))
if err != nil {
return nil, fmt.Errorf("parse html failed: %w", err)
} Defensive patterns
Strategy: fallback
Validate before calling
if strings.TrimSpace(fragment) == "" {
return []YunsoItem{}, nil
}
if !strings.Contains(fragment, "layui-card") {
log.Warn("yunso fragment missing expected markup")
} Type guard
func hasExpectedMarkup(fragment string) bool {
return strings.Contains(fragment, "layui-card") && strings.Contains(fragment, "data-qid")
} Try / catch
items, err := parseItems(fragment)
if err != nil {
log.Warn("yunso parse failed, returning empty", "err", err)
items = []YunsoItem{}
} Prevention
- Short-circuit on empty fragments before parsing
- Alert when selectors match zero cards — it usually means markup changed
- Pin goquery versions and test parsing against recorded fixtures
When it happens
Trigger: goquery.NewDocumentFromReader errors when parsing `<div id="yunso-root">` + fragment + `</div>` — e.g. apiResp.Data is empty or the fragment is not HTML as expected.
Common situations: The yunso API changed its result format (no longer HTML fragments), Data is empty/null for queries with no hits, or malformed HTML causes the underlying parser to fail.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/16146476f57ae40a.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/yunso/yunso.go:199
return nil, fmt.Errorf("read response failed: %w", err)
}
var apiResp YunsoAPIResponse
if err := jsonutil.Unmarshal(body, &apiResp); err != nil {
return nil, fmt.Errorf("decode response failed: %w", err)
}
if apiResp.Code != 0 {
return nil, fmt.Errorf("api returned error: %s", apiResp.Msg)
}
return p.parseItems(apiResp.Data)
}
func (p *YunsoAsyncPlugin) parseItems(fragment string) ([]YunsoItem, error) {
doc, err := goquery.NewDocumentFromReader(strings.NewReader(`<div id="yunso-root">` + fragment + `</div>`))
if err != nil {
return nil, fmt.Errorf("parse html failed: %w", err)
}
items := make([]YunsoItem, 0, 16)
doc.Find("div.layui-card[data-qid]").Each(func(_ int, card *goquery.Selection) {
anchor := card.Find(`a[onclick*="open_sid"]`).First()
if anchor.Length() == 0 {
return
}
title := cleanYunsoText(anchor.Text())
if title == "" {
return
}
encryptedURL, _ := anchor.Attr("url")
decryptedURL := ""
if encryptedURL != "" {
if decoded, err := decryptYunsoURL(encryptedURL); err == nil {View on GitHub (pinned to beaa561337)