fish2018/pansou · error

机器人验证出现循环

Error message

机器人验证出现循环

What it means

Raised when, after submitting the challenge verification, the returned page is still detected as a bot-challenge page (isBotChallengePage(respBody)), meaning verification entered a loop rather than granting access. The library aborts instead of retrying forever.

Solutions

  1. Reuse the SAME scraper instance across challenge fetch, submit, and retry so cookies persist.
  2. Check that saved cookies are applied via createScraperWithCookies and session refresh is disabled.
  3. Update the cloudscraper dependency — challenge format may have changed.
  4. Rotate exit IP/proxy; datacenter IPs often get perpetual challenges.

Example fix

// before
scraper := cloudscraper.New() // fresh instance per request, cookies lost
// after
scraper, _ := p.createScraperWithCookies(savedCookieStr) // reuse cookies + jar
Defensive patterns

Strategy: fallback

Validate before calling

if len(savedCookies) == 0 { /* re-login or fetch a fresh session before attempting challenge flow */ }

Try / catch

if err := p.fetch(url); err != nil { if strings.Contains(err.Error(), "机器人验证出现循环") { scraper = p.createScraperWithCookies(freshCookies); retryOnce() } }

Prevention

When it happens

Trigger: submitChallengeVerification POSTs the solved form, reads the body, and isBotChallengePage(body) is still true — the site returns another challenge page.

Common situations: Challenge cookies were not persisted (fresh scraper or cleared cookie jar), site upgraded its anti-bot (e.g. new Cloudflare turnstile), browser fingerprint/TLS signature rejected, or requests routed through IPs the site blocks (datacenter/proxy IPs).

Related errors


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

Appendix: source

Thrown at plugin/gying/gying.go:1883

}

func (p *GyingPlugin) submitChallengeVerification(scraper *cloudscraper.Scraper, requestURL string, form url.Values) error {
	resp, err := scraper.Post(requestURL, "application/x-www-form-urlencoded", strings.NewReader(form.Encode()))
	if err != nil {
		return fmt.Errorf("提交验证失败: %w", err)
	}
	defer resp.Body.Close()

	if DebugLog {
		fmt.Printf("[Gying] Challenge提交完成: url=%s status=%d\n", requestURL, resp.StatusCode)
	}

	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("读取验证响应失败: %w", err)
	}
	if isBotChallengePage(respBody) {
		return fmt.Errorf("机器人验证出现循环")
	}

	var verifyResp challengeVerifyResponse
	if err := json.Unmarshal(respBody, &verifyResp); err != nil {
		return fmt.Errorf("解析验证响应失败: %w", err)
	}
	if !verifyResp.Success {
		if verifyResp.Msg != "" {
			return fmt.Errorf("机器人验证失败: %s", verifyResp.Msg)
		}
		return fmt.Errorf("机器人验证失败")
	}

	if DebugLog {
		fmt.Printf("[Gying] Challenge验证成功: url=%s\n", requestURL)
	}

	return nil

View on GitHub (pinned to beaa561337)