package xiaohongshu import ( "context" "encoding/json" "fmt" "net/url" "time" "github.com/go-rod/rod" ) type SearchResult struct { Search struct { Feeds FeedsValue `json:"feeds"` } `json:"search"` } type SearchAction struct { page *rod.Page } func NewSearchAction(page *rod.Page) *SearchAction { pp := page.Timeout(60 * time.Second) return &SearchAction{page: pp} } func (s *SearchAction) Search(ctx context.Context, keyword string) ([]Feed, error) { page := s.page.Context(ctx) searchURL := makeSearchURL(keyword) page.MustNavigate(searchURL) page.MustWaitStable() page.MustWait(`() => window.__INITIAL_STATE__ !== undefined`) // 获取 window.__INITIAL_STATE__ 并转换为 JSON 字符串 result := page.MustEval(`() => { if (window.__INITIAL_STATE__) { return JSON.stringify(window.__INITIAL_STATE__); } return ""; }`).String() if result == "" { return nil, fmt.Errorf("__INITIAL_STATE__ not found") } var searchResult SearchResult if err := json.Unmarshal([]byte(result), &searchResult); err != nil { return nil, fmt.Errorf("failed to unmarshal __INITIAL_STATE__: %w", err) } return searchResult.Search.Feeds.Value, nil } func makeSearchURL(keyword string) string { values := url.Values{} values.Set("keyword", keyword) values.Set("source", "web_explore_feed") return fmt.Sprintf("https://www.xiaohongshu.com/search_result?%s", values.Encode()) }