fish2018/pansou · warning

[ ] 解析详情页失败

Error message

[%s] 解析详情页失败: %w

What it means

parseDetail hands the fetched HTML body to goquery.NewDocumentFromReader. goquery only errors when the underlying XML/HTML parser fails, which is rare; this error wraps that parser failure with the plugin name prefix. It means the document could not be constructed at all.

Solutions

  1. Verify the body passed to parseDetail is non-empty and is actually HTML (log a snippet on error)
  2. Since goquery tolerates most malformed HTML, check for a goquery/x-net-html version issue and update dependencies
  3. Rely on getDetailInfo's fallback: it continues to the next candidate URL, so ensure candidate list covers alternates
Defensive patterns

Strategy: try-catch

Try / catch

info, err := plugin.GetDetailInfo(ctx, url)
if err != nil && strings.Contains(err.Error(), "解析详情页失败") {
    log.Printf("goquery parse failed for %s: %v", url, err)
    return detailInfo{} // degrade gracefully; getDetailInfo already tries alternate URLs
}

Prevention

When it happens

Trigger: goquery.NewDocumentFromReader(strings.NewReader(body)) returns a non-nil error inside parseDetail, called from getDetailInfo after a successful fetch of a detail candidate URL.

Common situations: Practically triggered by an empty or nil reader state rather than truly invalid HTML (goquery's parser is lenient); a body containing extremely malformed content in strict parsing configurations.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/baa4b2abeed32cc5. Report an issue: GitHub.

Appendix: source

Thrown at plugin/qiwei/qiwei.go:420

	if isVerifyPage(string(responseBody)) {
		return fmt.Errorf("站点未接受验证参数")
	}
	return nil
}

func md5StringToHex(value string) string {
	var builder strings.Builder
	for _, r := range value {
		builder.WriteString(fmt.Sprintf("%d", r+1))
	}
	sum := md5.Sum([]byte(builder.String()))
	return hex.EncodeToString(sum[:])
}

func (p *QiweiPlugin) parseDetail(detailURL, body, fallbackTitle, fallbackPic string) (detailInfo, error) {
	doc, err := goquery.NewDocumentFromReader(strings.NewReader(body))
	if err != nil {
		return detailInfo{}, fmt.Errorf("[%s] 解析详情页失败: %w", p.Name(), err)
	}

	title := cleanText(doc.Find(".main-ui-meta h1").First().Text())
	title = yearSuffixRegex.ReplaceAllString(title, "")
	if title == "" {
		title = fallbackTitle
	}

	cover := normalizeURL(detailURL, attrOrEmpty(doc.Find(`meta[property="og:image"]`).First(), "content"))
	if cover == "" {
		cover = normalizeURL(detailURL, attrOrEmpty(doc.Find(".main-left .img img").First(), "src"))
	}
	if cover == "" {
		cover = fallbackPic
	}

	contentParts := make([]string, 0, 3)
	if meta := cleanText(doc.Find(".main-ui-meta .otherbox").First().Text()); meta != "" {

View on GitHub (pinned to beaa561337)