fish2018/pansou · error

未找到formhash值

Error message

未找到formhash值

What it means

getFormhash scrapes the site's HTML to extract the anti-CSRF 'formhash' value required by the search form. If, after parsing the document with goquery, no formhash value is found in any input field or URL, it returns this error. It means the fetched page did not contain the expected hidden form token.

Solutions

  1. Log the fetched HTML (enable DebugLog or dump resp body) to see what page was actually returned
  2. Set/refresh realistic request headers (User-Agent, Referer, cookies) in setRequestHeaders so the site serves the real page
  3. Update the formhash selector in getFormhash to match the current site markup
  4. Add retry logic — the page may load correctly on a second attempt
  5. Check whether the site now requires login or JS challenge solving

Example fix

// before
if formhash == "" {
    return "", fmt.Errorf("未找到formhash值")
}
// after
if formhash == "" {
    return "", fmt.Errorf("未找到formhash值 (page status body snippet: %.200s)", pageBody)
}
Defensive patterns

Strategy: retry

Validate before calling

// Before trusting the flow, verify the fetched page contains a formhash input
// (getFormhash's goquery scope) — e.g. in DebugLog:
// doc.Find("input[name='formhash']").Each(func(i int, s *goquery.Selection) {
//     fmt.Println("formhash:", s.AttrOr("value", ""))
// })
if err != nil { /* handle fetch failure */ }

Type guard

func hasFormhash(doc *goquery.Document) bool {
    return doc.Find("input[name='formhash']").Length() > 0
}

Try / catch

formhash, err := plugin.GetFormhash(ctx)
if err != nil {
    if strings.Contains(err.Error(), "未找到formhash值") {
        // page shape changed or was a block page — refresh cookies/headers and retry once
        return plugin.GetFormhash(ctx)
    }
    return err
}

Prevention

When it happens

Trigger: The GET request for the search page returned a login page, captcha page, Cloudflare challenge, or error page instead of the normal page containing <input name="formhash">; or the site's markup changed so the goquery selector no longer matches.

Common situations: Site is blocking the plugin's default User-Agent/headers; the target site changed its HTML template; the server redirected to an anti-bot interstitial; the site requires cookies/login to render the search form.

Related errors


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

Appendix: source

Thrown at plugin/qupanshe/qupanshe.go:211

	// 查找formhash
	formhash := ""
	inputCount := doc.Find("input[name='formhash']").Length()
	if DebugLog {
		fmt.Printf("[qupanshe] 找到input[name='formhash']元素数量: %d\n", inputCount)
	}

	doc.Find("input[name='formhash']").Each(func(i int, s *goquery.Selection) {
		if value, exists := s.Attr("value"); exists && value != "" {
			formhash = value
			if DebugLog {
				fmt.Printf("[qupanshe] 找到formhash[%d]: %s\n", i, value)
			}
		}
	})

	if formhash == "" {
		return "", fmt.Errorf("未找到formhash值")
	}

	return formhash, nil
}

// postSearchRequest 发送POST请求获取搜索结果URL
func (p *QupanshePlugin) postSearchRequest(client *http.Client, keyword, formhash string) (string, error) {
	// 添加延时,避免请求过快
	time.Sleep(2 * time.Second)

	// 构建POST请求
	searchURL := fmt.Sprintf("%s/search.php?mod=forum", BaseURL)
	data := url.Values{}
	data.Set("formhash", formhash)
	data.Set("srchtxt", keyword)
	data.Set("searchsubmit", "yes")

	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)

View on GitHub (pinned to beaa561337)