package xiaohongshu import ( "context" "log/slog" "time" "github.com/go-rod/rod" "github.com/go-rod/rod/lib/proto" "github.com/pkg/errors" ) // PublishImageContent 发布图文内容 type PublishImageContent struct { Title string Content string ImagePaths []string } type PublishAction struct { page *rod.Page } const ( urlOfPublic = `https://creator.xiaohongshu.com/publish/publish?source=official` ) func NewPublishImageAction(page *rod.Page) (*PublishAction, error) { pp := page.Timeout(60 * time.Second) pp.MustNavigate(urlOfPublic) pp.MustElement(`div.upload-content`).MustWaitVisible() slog.Info("wait for upload-content visible success") // 等待一段时间确保页面完全加载 time.Sleep(1 * time.Second) createElems := pp.MustElements("div.creator-tab") slog.Info("foundcreator-tab elements", "count", len(createElems)) for _, elem := range createElems { text, err := elem.Text() if err != nil { slog.Error("获取元素文本失败", "error", err) continue } if text == "上传图文" { if err := elem.Click(proto.InputMouseButtonLeft, 1); err != nil { slog.Error("点击元素失败", "error", err) continue } break } } time.Sleep(1 * time.Second) return &PublishAction{ page: pp, }, nil } func (p *PublishAction) Publish(ctx context.Context, content PublishImageContent) error { if len(content.ImagePaths) == 0 { return errors.New("图片不能为空") } page := p.page.Context(ctx) if err := uploadImages(page, content.ImagePaths); err != nil { return errors.Wrap(err, "小红书上传图片失败") } if err := submitPublish(page, content.Title, content.Content); err != nil { return errors.Wrap(err, "小红书发布失败") } return nil } func uploadImages(page *rod.Page, imagesPaths []string) error { pp := page.Timeout(30 * time.Second) // 等待上传输入框出现 uploadInput := pp.MustElement(".upload-input") // 上传多个文件 uploadInput.MustSetFiles(imagesPaths...) // 等待上传完成 time.Sleep(1 * time.Second) return nil } func submitPublish(page *rod.Page, title, content string) error { titleElem := page.MustElement("div.d-input input") titleElem.MustInput(title) time.Sleep(1 * time.Second) contentElem := page.MustElement("div.ql-editor") contentElem.MustInput(content) time.Sleep(1 * time.Second) submitButton := page.MustElement("div.submit div.d-button-content") submitButton.MustClick() time.Sleep(5 * time.Second) return nil }