-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathredbook-poster.js
More file actions
186 lines (158 loc) · 5.75 KB
/
redbook-poster.js
File metadata and controls
186 lines (158 loc) · 5.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/**
* 小红书自动发稿服务
*/
import { chromium } from 'playwright';
import fs from "fs";
import path from "path";
export class RedbookPoster {
constructor(jsonPath = "/tmp") {
this.cookiesFile = path.join(jsonPath, "redbook_cookies.json");
this.browser = null;
this.context = null;
this.page = null;
}
async init() {
this.browser = await chromium.launch({
headless: false
});
this.context = await this.browser.newContext();
this.page = await this.context.newPage();
}
async _loadCookies() {
if (fs.existsSync(this.cookiesFile)) {
try {
const cookies = JSON.parse(fs.readFileSync(this.cookiesFile, "utf8"));
await this.page.goto("https://creator.xiaohongshu.com");
await this.context.addCookies(cookies);
} catch (err) {
console.error("Error loading cookies:", err);
}
}
}
async _saveCookies() {
const cookies = await this.context.cookies();
fs.writeFileSync(this.cookiesFile, JSON.stringify(cookies));
}
async login(phone, verificationCode = "") {
if (!this.browser) await this.init();
// 加载cookies进行登录
await this.page.goto("https://creator.xiaohongshu.com/login");
await this._loadCookies();
await this.page.reload();
await this.page.waitForTimeout(3000);
// 检查是否已经登录
const currentUrl = this.page.url();
if (currentUrl !== "https://creator.xiaohongshu.com/login") {
await this._saveCookies();
await this.page.waitForTimeout(2000);
return;
} else {
// 清理无效的cookies
await this.context.clearCookies();
}
// 如果cookies登录失败,则进行手动登录
await this.page.goto("https://creator.xiaohongshu.com/login");
// 等待登录页面加载完成
await this.page.waitForTimeout(5000);
// 定位手机号输入框
const phoneInput = await this.page.waitForSelector('input[placeholder="手机号"]', { timeout: 10000 });
await phoneInput.fill('');
await phoneInput.fill(phone);
// 如果验证码为空,则点击发送验证码按钮
if (!verificationCode) {
try {
const sendCodeBtn = await this.page.waitForSelector(".css-uyobdj", { timeout: 10000 });
await sendCodeBtn.click();
} catch (e) {
try {
const sendCodeBtn = await this.page.waitForSelector(".css-1vfl29", { timeout: 10000 });
await sendCodeBtn.click();
} catch (e) {
try {
const sendCodeBtn = await this.page.waitForSelector("button:has-text('发送验证码')", { timeout: 10000 });
await sendCodeBtn.click();
} catch (e) {
console.error("无法找到发送验证码按钮");
}
}
}
return {
message: "验证码已发送,请将其配置到环境变量 verificationCode 中",
};
}
// 输入验证码
const codeInput = await this.page.waitForSelector('input[placeholder="验证码"]', { timeout: 10000 });
await codeInput.fill('');
await codeInput.fill(verificationCode);
// 点击登录按钮
const loginButton = await this.page.waitForSelector(".beer-login-btn", { timeout: 10000 });
await loginButton.click();
// 等待登录成功,保存cookies
await this.page.waitForTimeout(3000);
await this._saveCookies();
}
async postArticle(title, content, images = []) {
// 点击发布按钮
const publishBtn = await this.page.waitForSelector(".btn.el-tooltip__trigger.el-tooltip__trigger", { timeout: 10000 });
await publishBtn.click();
// 如果是发布图文,则切换到上传图文
await this.page.waitForTimeout(2000);
const tabs = await this.page.$$(".creator-tab");
if (tabs.length > 1) {
await tabs[1].click();
}
await this.page.waitForTimeout(2000);
// 上传图片
if (images.length > 0) {
const uploadInput = await this.page.$(".upload-input");
await uploadInput.setInputFiles(images);
await this.page.waitForTimeout(1000);
}
await this.page.waitForTimeout(2000);
// 输入标题 (限制为20字)
title = title.substring(0, 20);
const titleInput = await this.page.waitForSelector(".d-text", { timeout: 10000 });
await titleInput.fill(title);
// 输入内容
const contentInput = await this.page.waitForSelector(".ql-editor", { timeout: 10000 });
await contentInput.fill(content);
// 发布
await this.page.waitForTimeout(2000);
const submitBtn = await this.page.$(".publishBtn");
await submitBtn.click();
await this.page.waitForTimeout(2000);
}
async postVideoArticle(title, content, videos = []) {
// 点击发布按钮
await this.page.waitForTimeout(3000);
const publishBtn = await this.page.waitForSelector(".btn.el-tooltip__trigger.el-tooltip__trigger", { timeout: 10000 });
await publishBtn.click();
// 上传视频
await this.page.waitForTimeout(3000);
if (videos.length > 0) {
const uploadInput = await this.page.$(".upload-input");
await uploadInput.setInputFiles(videos);
await this.page.waitForTimeout(1000);
}
await this.page.waitForTimeout(3000);
// 输入标题
const titleInput = await this.page.waitForSelector(".d-text", { timeout: 10000 });
await titleInput.fill(title);
// 输入内容
const contentInput = await this.page.waitForSelector(".ql-editor", { timeout: 10000 });
await contentInput.fill(content);
// 发布
await this.page.waitForTimeout(6000);
const submitBtn = await this.page.$(".publishBtn");
await submitBtn.click();
await this.page.waitForTimeout(3000);
}
async close() {
if (this.browser) {
await this.browser.close();
this.browser = null;
this.context = null;
this.page = null;
}
}
}