fish2018/pansou · error

详情页HTML解析失败

Error message

详情页HTML解析失败: %w

What it means

goquery.NewDocumentFromReader failed while parsing the detail-page response body into an HTML document. goquery returns this error when reading the body stream fails (goquery itself does not validate HTML; malformed HTML still parses leniently).

Solutions

  1. Retry the request — a truncated body is usually transient network corruption.
  2. Ensure automatic decompression: set Transport.DisableCompression=false or use httputil to handle gzip; don't set Accept-Encoding manually without decoding.
  3. Check that resp.Body wasn't read before this call (e.g. by a debug logger).
  4. Capture and log the underlying read error (errors.Unwrap) to confirm I/O vs decompression.

Example fix

// before
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
    return nil, fmt.Errorf("详情页HTML解析失败: %w", err)
}
// after
body, rerr := io.ReadAll(resp.Body)
if rerr != nil {
    return nil, fmt.Errorf("读取详情页响应体失败: %w", rerr)
}
doc, err := goquery.NewDocumentFromReader(bytes.NewReader(body))
if err != nil {
    return nil, fmt.Errorf("详情页HTML解析失败: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

body, err := io.ReadAll(resp.Body)
if err != nil || len(body) == 0 {
    return // truncated/empty body, retry the request
}

Type guard

func isBodyReadError(err error) bool {
    return err != nil && (errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF))
}

Try / catch

results, err := plugin.Search(keyword)
if err != nil && strings.Contains(err.Error(), "详情页HTML解析失败") {
    // transient I/O on the body: retry once
    results, err = plugin.Search(keyword)
}

Prevention

When it happens

Trigger: Reading resp.Body returned an I/O error: connection dropped mid-body, gzip/deflate decompression failure due to a corrupted or truncated response, or the body was already partially consumed.

Common situations: Unstable network cutting the response short; server advertises Content-Encoding: gzip but sends invalid data; a proxy mangling the response; very large pages hitting an underlying read limit.

Related errors


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

Appendix: source

Thrown at plugin/pianku/pianku.go:405

	// 设置请求头
	p.setRequestHeaders(req)
	
	// 发送HTTP请求
	resp, err := p.doRequestWithRetry(req, client)
	if err != nil {
		return nil, fmt.Errorf("详情页请求失败: %w", err)
	}
	defer resp.Body.Close()
	
	// 检查状态码
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("详情页请求返回状态码: %d", resp.StatusCode)
	}
	
	// 解析HTML
	doc, err := goquery.NewDocumentFromReader(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("详情页HTML解析失败: %w", err)
	}
	
	// 提取下载链接
	return p.extractDownloadLinks(doc), nil
}

// extractDownloadLinks 提取详情页中的下载链接
func (p *PiankuPlugin) extractDownloadLinks(doc *goquery.Document) []model.Link {
	var links []model.Link
	seenURLs := make(map[string]bool) // 用于去重
	
	// 查找下载链接区域
	doc.Find("#donLink .down-list2").Each(func(i int, s *goquery.Selection) {
		linkURL, exists := s.Find(".down-list3 a").Attr("href")
		if !exists || linkURL == "" {
			return
		}
		

View on GitHub (pinned to beaa561337)