Files
xiaohongshu-mcp/xiaohongshu/feeds.go
zy aa09687751 feat: 添加搜索功能 (#16)
- 新增 SearchFeeds 服务方法,支持关键词搜索小红书内容
- 添加 search_feeds MCP 工具,提供搜索接口
- 新增 /api/v1/feeds/search API 端点
- 实现搜索页面的浏览器自动化操作
- 优化 MCP 协议支持,处理 notifications/initialized 和 notifications/cancelled 通知
- 更新文档,添加搜索功能说明和使用示例
- 重构类型定义,优化数据结构

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-17 23:35:22 +08:00

56 lines
1.2 KiB
Go

package xiaohongshu
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/go-rod/rod"
)
type FeedsListAction struct {
page *rod.Page
}
// FeedsResult 定义页面初始状态结构
type FeedsResult struct {
Feed FeedData `json:"feed"`
}
func NewFeedsListAction(page *rod.Page) *FeedsListAction {
pp := page.Timeout(60 * time.Second)
pp.MustNavigate("https://www.xiaohongshu.com")
pp.MustWaitStable()
pp.MustWait(`() => window.__INITIAL_STATE__ !== undefined`)
return &FeedsListAction{page: pp}
}
// GetFeedsList 获取页面的 Feed 列表数据
func (f *FeedsListAction) GetFeedsList(ctx context.Context) ([]Feed, error) {
page := f.page.Context(ctx)
// 获取 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")
}
// 解析完整的 InitialState
var state FeedsResult
if err := json.Unmarshal([]byte(result), &state); err != nil {
return nil, fmt.Errorf("failed to unmarshal __INITIAL_STATE__: %w", err)
}
// 返回 feed.feeds._value
return state.Feed.Feeds.Value, nil
}