fish2018/pansou · error

未找到DToken

Error message

未找到DToken

What it means

getToken scraped the token page successfully but no script tag contained a DToken definition, so the token variable stayed empty. The plugin depends on this client-side token to build authenticated search requests; without it searching is impossible. This is a page-structure/anti-bot change on the upstream site rather than a network fault.

Solutions

  1. Fetch the token page manually and inspect script contents to find the new token variable name or delivery mechanism
  2. Update the extraction regex/selector in getToken to match the current script pattern
  3. Check whether the token now comes from a cookie (e.g. DToken cookie) or a JSON endpoint and scrape that instead
  4. Detect challenge pages (markers like 'captcha'/'verify') and surface a clearer error instead of '未找到DToken'

Example fix

// before
if token == "" {
    return "", fmt.Errorf("未找到DToken")
}
// after
if token == "" {
    return "", fmt.Errorf("未找到DToken: token页面结构可能已变更或返回了验证页面 (url=%s, len=%d)", tokenURL, len(pageHTML))
}
Defensive patterns

Strategy: fallback

Validate before calling

html, _ := io.ReadAll(resp.Body)
if !strings.Contains(string(html), "DToken") {
    return fmt.Errorf("token page no longer exposes DToken; scraper needs update")
}

Try / catch

token, err := getToken(ctx)
if errors.Is(err, errDTokenNotFound) {
    return scrapeTokenFromCookieJar(client) // alternate extraction path
}

Prevention

When it happens

Trigger: After iterating doc.Find("script"), token == "" — the DToken regex found no match in any inline script (site renamed the variable, moved token into external JS/headers, or served a challenge page with 200).

Common situations: Upstream site updated its front-end and renamed/moved DToken; served a consent/anti-bot page with HTTP 200; token now delivered via cookie or API endpoint instead of inline script.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at plugin/xys/xys.go:195

	// 查找script标签中的DToken定义
	var token string
	doc.Find("script").Each(func(i int, s *goquery.Selection) {
		scriptContent := s.Text()
		if strings.Contains(scriptContent, "DToken") {
			// 使用正则表达式提取token
			re := regexp.MustCompile(`const\s+DToken\s*=\s*"([^"]+)"`)
			matches := re.FindStringSubmatch(scriptContent)
			if len(matches) > 1 {
				token = matches[1]
				if p.debugMode {
					log.Printf("[XYS] 从script中提取到token: %s", token[:10]+"...")
				}
			}
		}
	})

	if token == "" {
		return "", fmt.Errorf("未找到DToken")
	}

	// 缓存token
	p.tokenCache.Store(cacheKey, TokenCache{
		Token:     token,
		Timestamp: time.Now(),
	})

	return token, nil
}

// doRequestWithRetry 带重试机制的HTTP请求
func (p *XysPlugin) doRequestWithRetry(req *http.Request, client *http.Client) (*http.Response, error) {
	maxRetries := 3
	var lastErr error
	
	for i := 0; i < maxRetries; i++ {
		if i > 0 {

View on GitHub (pinned to beaa561337)