fish2018/pansou · error

获取验证脚本失败

Error message

获取验证脚本失败: %w

What it means

After locating the verification script URL, solveVerification downloads the JS file with fetchBody. If that HTTP fetch fails (network error, timeout, non-OK status handled by fetchBody), the error is wrapped with this message and returned, aborting the verification solve. The %w wrapping preserves the underlying network/HTTP error for errors.Is/As inspection.

Solutions

  1. Print/check the wrapped cause (errors.Unwrap) to see if it's a timeout, DNS failure, or HTTP status, and fix accordingly.
  2. Verify normalizeURL(pageURL, scriptMatch[1]) yields the correct absolute script URL — a bad base or relative path yields a 404.
  3. Ensure the request carries the site's cookies/Referer (same client with cookie jar) since the script host may reject unauthenticated fetches.
  4. Increase detailTimeout if the script host is slow, or retry the fetch with backoff.
  5. Check whether the script URL changed on the site and update the fetch or add a fallback mirror path.

Example fix

// before
jsBody, err := p.fetchBody(client, scriptURL, pageURL, detailTimeout)
if err != nil {
    return fmt.Errorf("获取验证脚本失败: %w", err)
}
// after
jsBody, err := p.fetchBody(client, scriptURL, pageURL, detailTimeout)
if err != nil {
    return fmt.Errorf("获取验证脚本失败 (url=%s): %w", scriptURL, err) // include URL for diagnosis
}
Defensive patterns

Strategy: retry

Validate before calling

// sanity-check the absolute script URL before fetching
abs := normalizeURL(pageURL, scriptMatch[1])
if u, err := neturl.Parse(abs); err != nil || u.Host == "" {
    return fmt.Errorf("invalid verification script URL derived from %s", pageURL)
}

Type guard

func isScriptFetchErr(err error) bool {
    var ne net.Error
    return err != nil && (errors.As(err, &ne) || strings.Contains(err.Error(), "获取验证脚本失败"))
}

Try / catch

if err := plugin.SolveVerification(client, pageURL, body); err != nil {
    var netErr net.Error
    if errors.As(err, &netErr) && netErr.Timeout() {
        // transient: retry once with a longer timeout
        time.Sleep(time.Second)
        return plugin.SolveVerification(client, pageURL, body)
    }
    return err
}

Prevention

When it happens

Trigger: In solveVerification, p.fetchBody(client, scriptURL, pageURL, detailTimeout) returns a non-nil error while downloading the verification challenge JS from the host serving the slider script.

Common situations: The script host blocks datacenter IPs or requires a Referer/cookie the client isn't sending; scriptURL is relative and normalizeURL produced a wrong absolute URL; detailTimeout is too short for a slow script CDN; the site moved or removed the verification script (404).

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at plugin/qiwei/qiwei.go:359

	if lastErr == nil {
		lastErr = fmt.Errorf("[%s] 获取详情失败: %s", p.Name(), detailURL)
	}
	return detailInfo{}, lastErr
}

// solveVerification completes the site's deterministic slider challenge. The
// challenge is session-bound, so the caller and this method must share a
// cookie jar on the same http.Client.
func (p *QiweiPlugin) solveVerification(client *http.Client, pageURL, verifyHTML string) error {
	scriptMatch := verificationScriptRegex.FindStringSubmatch(verifyHTML)
	if len(scriptMatch) < 2 {
		return fmt.Errorf("未找到滑动验证脚本")
	}
	scriptURL := normalizeURL(pageURL, scriptMatch[1])
	jsBody, err := p.fetchBody(client, scriptURL, pageURL, detailTimeout)
	if err != nil {
		return fmt.Errorf("获取验证脚本失败: %w", err)
	}

	typeMatch := verificationTypeRegex.FindStringSubmatch(jsBody)
	keyMatch := verificationKeyRegex.FindStringSubmatch(jsBody)
	valueMatch := verificationValueRegex.FindStringSubmatch(jsBody)
	if len(typeMatch) < 2 || len(keyMatch) < 2 || len(valueMatch) < 2 {
		return fmt.Errorf("验证脚本参数不完整")
	}

	encodedValue := md5StringToHex(valueMatch[1])
	endpointPath := "/a20be899_96a6_40b2_88ba_32f1f75f1552_yanzheng_huadong.php"
	if endpointMatch := verificationEndpointRegex.FindStringSubmatch(jsBody); len(endpointMatch) > 1 {
		endpointPath = "/" + endpointMatch[1]
	}
	parsedPage, err := url.Parse(pageURL)
	if err != nil {
		return fmt.Errorf("验证页面地址无效: %w", err)
	}

View on GitHub (pinned to beaa561337)