@easyasstudio/xhs-cli 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +29 -0
- package/LICENSE +641 -0
- package/README.md +108 -0
- package/dist/browser/cookie.d.ts +1 -0
- package/dist/browser/cookie.d.ts.map +1 -0
- package/dist/browser/cookie.js +2 -0
- package/dist/browser/cookie.js.map +1 -0
- package/dist/browser/index.d.ts +7 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +201 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/cli/cliRouter.d.ts +6 -0
- package/dist/cli/cliRouter.d.ts.map +1 -0
- package/dist/cli/cliRouter.js +249 -0
- package/dist/cli/cliRouter.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +18 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/parseArgs.d.ts +13 -0
- package/dist/cli/parseArgs.d.ts.map +1 -0
- package/dist/cli/parseArgs.js +64 -0
- package/dist/cli/parseArgs.js.map +1 -0
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +67 -0
- package/dist/config.js.map +1 -0
- package/dist/toolset/accountRegistry.d.ts +33 -0
- package/dist/toolset/accountRegistry.d.ts.map +1 -0
- package/dist/toolset/accountRegistry.js +198 -0
- package/dist/toolset/accountRegistry.js.map +1 -0
- package/dist/toolset/cachePaths.d.ts +3 -0
- package/dist/toolset/cachePaths.d.ts.map +1 -0
- package/dist/toolset/cachePaths.js +7 -0
- package/dist/toolset/cachePaths.js.map +1 -0
- package/dist/toolset/get_metrics.d.ts +47 -0
- package/dist/toolset/get_metrics.d.ts.map +1 -0
- package/dist/toolset/get_metrics.js +201 -0
- package/dist/toolset/get_metrics.js.map +1 -0
- package/dist/toolset/get_note_detail.d.ts +3 -0
- package/dist/toolset/get_note_detail.d.ts.map +1 -0
- package/dist/toolset/get_note_detail.js +100 -0
- package/dist/toolset/get_note_detail.js.map +1 -0
- package/dist/toolset/get_profile.d.ts +16 -0
- package/dist/toolset/get_profile.d.ts.map +1 -0
- package/dist/toolset/get_profile.js +79 -0
- package/dist/toolset/get_profile.js.map +1 -0
- package/dist/toolset/get_recent_posts.d.ts +3 -0
- package/dist/toolset/get_recent_posts.d.ts.map +1 -0
- package/dist/toolset/get_recent_posts.js +113 -0
- package/dist/toolset/get_recent_posts.js.map +1 -0
- package/dist/toolset/index.d.ts +12 -0
- package/dist/toolset/index.d.ts.map +1 -0
- package/dist/toolset/index.js +48 -0
- package/dist/toolset/index.js.map +1 -0
- package/dist/toolset/login.d.ts +4 -0
- package/dist/toolset/login.d.ts.map +1 -0
- package/dist/toolset/login.js +194 -0
- package/dist/toolset/login.js.map +1 -0
- package/dist/toolset/post.d.ts +27 -0
- package/dist/toolset/post.d.ts.map +1 -0
- package/dist/toolset/post.js +148 -0
- package/dist/toolset/post.js.map +1 -0
- package/dist/toolset/postValidate.d.ts +8 -0
- package/dist/toolset/postValidate.d.ts.map +1 -0
- package/dist/toolset/postValidate.js +59 -0
- package/dist/toolset/postValidate.js.map +1 -0
- package/dist/toolset/publishButton.d.ts +7 -0
- package/dist/toolset/publishButton.d.ts.map +1 -0
- package/dist/toolset/publishButton.js +28 -0
- package/dist/toolset/publishButton.js.map +1 -0
- package/dist/toolset/publishedRecords.d.ts +15 -0
- package/dist/toolset/publishedRecords.d.ts.map +1 -0
- package/dist/toolset/publishedRecords.js +60 -0
- package/dist/toolset/publishedRecords.js.map +1 -0
- package/dist/toolset/sessionResolve.d.ts +12 -0
- package/dist/toolset/sessionResolve.d.ts.map +1 -0
- package/dist/toolset/sessionResolve.js +39 -0
- package/dist/toolset/sessionResolve.js.map +1 -0
- package/dist/toolset/sessionTypes.d.ts +13 -0
- package/dist/toolset/sessionTypes.d.ts.map +1 -0
- package/dist/toolset/sessionTypes.js +3 -0
- package/dist/toolset/sessionTypes.js.map +1 -0
- package/dist/utils/cache.d.ts +10 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +124 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/titleToFilename.d.ts +2 -0
- package/dist/utils/titleToFilename.d.ts.map +1 -0
- package/dist/utils/titleToFilename.js +19 -0
- package/dist/utils/titleToFilename.js.map +1 -0
- package/dist/utils/version_check.d.ts +2 -0
- package/dist/utils/version_check.d.ts.map +1 -0
- package/dist/utils/version_check.js +105 -0
- package/dist/utils/version_check.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { withLoggedInPage } from '../browser/index.js';
|
|
2
|
+
import { saveToCache, loadFromCache } from '../utils/cache.js';
|
|
3
|
+
import { prefixedCacheFilename } from './cachePaths.js';
|
|
4
|
+
function findMetric(source, keywords) {
|
|
5
|
+
for (const keyword of keywords) {
|
|
6
|
+
const item = source.find((row) => row.title.includes(keyword));
|
|
7
|
+
if (item)
|
|
8
|
+
return item.number;
|
|
9
|
+
}
|
|
10
|
+
return '0';
|
|
11
|
+
}
|
|
12
|
+
function formatOperationSnapshot(snapshot) {
|
|
13
|
+
const lines = [
|
|
14
|
+
`日期: ${snapshot.date}`,
|
|
15
|
+
'',
|
|
16
|
+
'【概览】',
|
|
17
|
+
`总粉丝: ${snapshot.totalFans} 新增: ${snapshot.newFans} 流失: ${snapshot.lostFans} 净增: ${snapshot.netFansGrowth}`,
|
|
18
|
+
`点赞: ${snapshot.totalLikes} 收藏: ${snapshot.totalCollects} 评论: ${snapshot.totalComments} 分享: ${snapshot.totalShares}`,
|
|
19
|
+
`笔记数: ${snapshot.publishedNotes} 阅读: ${snapshot.noteReads} 阅读率: ${snapshot.noteReadRate} 平均阅读时长: ${snapshot.avgReadTime}`,
|
|
20
|
+
`主页访客: ${snapshot.homePageVisitors}`,
|
|
21
|
+
'',
|
|
22
|
+
];
|
|
23
|
+
if (snapshot.tendencies.length > 0) {
|
|
24
|
+
lines.push('【首页指标趋势】');
|
|
25
|
+
for (const t of snapshot.tendencies) {
|
|
26
|
+
const dir = t.tendency === 'up' ? '↑' : t.tendency === 'down' ? '↓' : '—';
|
|
27
|
+
lines.push(` ${t.metric}: ${dir} ${t.value}`);
|
|
28
|
+
}
|
|
29
|
+
lines.push('');
|
|
30
|
+
}
|
|
31
|
+
if (snapshot.trafficSources.length > 0) {
|
|
32
|
+
lines.push('【流量来源】');
|
|
33
|
+
for (const s of snapshot.trafficSources) {
|
|
34
|
+
lines.push(` ${s.name}: ${s.percentage}`);
|
|
35
|
+
}
|
|
36
|
+
lines.push('');
|
|
37
|
+
}
|
|
38
|
+
if (snapshot.fanInterests.length > 0) {
|
|
39
|
+
lines.push('【粉丝兴趣】');
|
|
40
|
+
lines.push(` ${snapshot.fanInterests.join('、')}`);
|
|
41
|
+
}
|
|
42
|
+
return lines.join('\n').trimEnd();
|
|
43
|
+
}
|
|
44
|
+
/** 统一的页面数据获取器 */
|
|
45
|
+
export class XHSOperationDataFetcher {
|
|
46
|
+
page;
|
|
47
|
+
constructor(page) {
|
|
48
|
+
this.page = page;
|
|
49
|
+
}
|
|
50
|
+
async fetchAllData() {
|
|
51
|
+
const homeData = await this.fetchHomeData();
|
|
52
|
+
const fanData = await this.fetchFanData();
|
|
53
|
+
const trafficSources = await this.fetchTrafficSources();
|
|
54
|
+
return this.transformToSnapshot(homeData, fanData, trafficSources);
|
|
55
|
+
}
|
|
56
|
+
async fetchHomeData() {
|
|
57
|
+
await this.navigate('https://creator.xiaohongshu.com/new/home');
|
|
58
|
+
const rows = await this.page.$$eval('.creator-block', (blocks) => {
|
|
59
|
+
return blocks
|
|
60
|
+
.map((block) => {
|
|
61
|
+
const titleEl = block.querySelector('.title');
|
|
62
|
+
const numberEl = block.querySelector('.number');
|
|
63
|
+
const tendencyEl = block.querySelector('.tendency');
|
|
64
|
+
if (!titleEl || !numberEl)
|
|
65
|
+
return null;
|
|
66
|
+
let tendency = 'none';
|
|
67
|
+
let tendencyValue = '--';
|
|
68
|
+
if (tendencyEl) {
|
|
69
|
+
const tendencyNumberEl = tendencyEl.querySelector('.tendency-number');
|
|
70
|
+
if (tendencyNumberEl) {
|
|
71
|
+
tendencyValue = (tendencyNumberEl.textContent || '').trim() || '--';
|
|
72
|
+
const classList = Array.from(tendencyNumberEl.classList);
|
|
73
|
+
if (classList.includes('up'))
|
|
74
|
+
tendency = 'up';
|
|
75
|
+
else if (classList.includes('down'))
|
|
76
|
+
tendency = 'down';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
title: (titleEl.textContent || '').trim(),
|
|
81
|
+
number: (numberEl.textContent || '').trim() || '0',
|
|
82
|
+
tendency,
|
|
83
|
+
tendencyValue,
|
|
84
|
+
};
|
|
85
|
+
})
|
|
86
|
+
.filter((item) => item !== null);
|
|
87
|
+
});
|
|
88
|
+
return rows;
|
|
89
|
+
}
|
|
90
|
+
async fetchFanData() {
|
|
91
|
+
await this.navigate('https://creator.xiaohongshu.com/creator/fans');
|
|
92
|
+
return await this.page.evaluate(() => {
|
|
93
|
+
const data = {
|
|
94
|
+
totalFans: '0',
|
|
95
|
+
newFans: '0',
|
|
96
|
+
lostFans: '0',
|
|
97
|
+
interests: [],
|
|
98
|
+
};
|
|
99
|
+
document.querySelectorAll('.block-container').forEach((container) => {
|
|
100
|
+
const desEl = container.querySelector('.des');
|
|
101
|
+
const conEl = container.querySelector('.con');
|
|
102
|
+
if (desEl && conEl) {
|
|
103
|
+
const description = (desEl.textContent || '').trim();
|
|
104
|
+
const value = (conEl.textContent || '').trim().replace(/,/g, '');
|
|
105
|
+
if (description.includes('总粉丝数')) {
|
|
106
|
+
data.totalFans = value;
|
|
107
|
+
}
|
|
108
|
+
else if (description.includes('新增粉丝数')) {
|
|
109
|
+
const match = value.match(/\d+/);
|
|
110
|
+
data.newFans = match ? match[0] : '0';
|
|
111
|
+
}
|
|
112
|
+
else if (description.includes('流失粉丝数')) {
|
|
113
|
+
const match = value.match(/\d+/);
|
|
114
|
+
data.lostFans = match ? match[0] : '0';
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
const wordCloudBox = document.querySelector('.word-cloud-box');
|
|
119
|
+
if (wordCloudBox) {
|
|
120
|
+
data.interests = Array.from(wordCloudBox.querySelectorAll('.row-item'))
|
|
121
|
+
.map((item) => (item.textContent || '').trim())
|
|
122
|
+
.filter((text) => text);
|
|
123
|
+
}
|
|
124
|
+
return data;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
async fetchTrafficSources() {
|
|
128
|
+
await this.navigate('https://creator.xiaohongshu.com/statistics/account');
|
|
129
|
+
return await this.page.evaluate(() => {
|
|
130
|
+
const sources = [];
|
|
131
|
+
const container = document.querySelector('#creator-account-fans-graph');
|
|
132
|
+
if (!container)
|
|
133
|
+
return sources;
|
|
134
|
+
const text = container.textContent || '';
|
|
135
|
+
const regex = /([^:::\s]+)[:::]\s*(\d+(?:\.\d+)?%)/g;
|
|
136
|
+
let match;
|
|
137
|
+
const seen = new Set();
|
|
138
|
+
while ((match = regex.exec(text)) !== null) {
|
|
139
|
+
const name = match[1].trim();
|
|
140
|
+
const percentage = match[2].trim();
|
|
141
|
+
if (name && percentage && !seen.has(name)) {
|
|
142
|
+
seen.add(name);
|
|
143
|
+
sources.push({ name, percentage });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return sources;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
async navigate(url) {
|
|
150
|
+
await this.page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
|
|
151
|
+
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
152
|
+
}
|
|
153
|
+
transformToSnapshot(homeData, fanData, trafficSources) {
|
|
154
|
+
const newFansNum = parseInt(fanData.newFans, 10) || 0;
|
|
155
|
+
const lostFansNum = parseInt(fanData.lostFans, 10) || 0;
|
|
156
|
+
const homePageVisitors = findMetric(homeData, ['主页访客']);
|
|
157
|
+
return {
|
|
158
|
+
date: new Date().toISOString().split('T')[0],
|
|
159
|
+
totalFans: fanData.totalFans,
|
|
160
|
+
newFans: fanData.newFans,
|
|
161
|
+
lostFans: fanData.lostFans,
|
|
162
|
+
netFansGrowth: (newFansNum - lostFansNum).toString(),
|
|
163
|
+
totalLikes: findMetric(homeData, ['点赞']),
|
|
164
|
+
totalCollects: findMetric(homeData, ['收藏']),
|
|
165
|
+
totalComments: findMetric(homeData, ['评论']),
|
|
166
|
+
totalShares: findMetric(homeData, ['分享']),
|
|
167
|
+
publishedNotes: findMetric(homeData, ['笔记']),
|
|
168
|
+
noteReads: findMetric(homeData, ['阅读']),
|
|
169
|
+
noteReadRate: findMetric(homeData, ['阅读率']),
|
|
170
|
+
avgReadTime: findMetric(homeData, ['时长', '平均']),
|
|
171
|
+
homePageVisitors,
|
|
172
|
+
trafficSources,
|
|
173
|
+
fanInterests: fanData.interests,
|
|
174
|
+
tendencies: homeData.map((item) => ({
|
|
175
|
+
metric: item.title,
|
|
176
|
+
tendency: item.tendency,
|
|
177
|
+
value: item.tendencyValue,
|
|
178
|
+
})),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* 获取运营数据(纯文本;同日缓存命中则直接返回文本)
|
|
184
|
+
* @param session 浏览器目录与缓存命名空间(多账号)
|
|
185
|
+
*/
|
|
186
|
+
export async function getOperationData(session) {
|
|
187
|
+
const today = new Date().toISOString().split('T')[0];
|
|
188
|
+
const cacheFilename = prefixedCacheFilename(session.cachePathPrefix, `operation_data/${today}_text.json`);
|
|
189
|
+
const cached = loadFromCache(cacheFilename);
|
|
190
|
+
if (cached && cached.date === today && cached.text?.trim()) {
|
|
191
|
+
return cached.text;
|
|
192
|
+
}
|
|
193
|
+
const snapshot = await withLoggedInPage(async (page) => {
|
|
194
|
+
const fetcher = new XHSOperationDataFetcher(page);
|
|
195
|
+
return await fetcher.fetchAllData();
|
|
196
|
+
}, session.browserUserDataDir);
|
|
197
|
+
const text = formatOperationSnapshot(snapshot);
|
|
198
|
+
saveToCache(cacheFilename, { date: today, text });
|
|
199
|
+
return text;
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=get_metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_metrics.js","sourceRoot":"","sources":["../../src/toolset/get_metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_note_detail.d.ts","sourceRoot":"","sources":["../../src/toolset/get_note_detail.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAoGzD,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,MAAM,CAAC,CA6BjB"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { withLoggedInPage } from '../browser/index.js';
|
|
2
|
+
import { saveToCache, loadFromCache } from '../utils/cache.js';
|
|
3
|
+
import { prefixedCacheFilename } from './cachePaths.js';
|
|
4
|
+
function normalizeNoteId(noteId) {
|
|
5
|
+
return noteId.trim();
|
|
6
|
+
}
|
|
7
|
+
function formatNoteDetail(noteId, detail) {
|
|
8
|
+
const lines = [
|
|
9
|
+
`ID: ${noteId}`,
|
|
10
|
+
`标题: ${detail.title || '未知标题'}`,
|
|
11
|
+
`发布时间: ${detail.publishTime || '未知'}`,
|
|
12
|
+
`编辑页: ${detail.editorUrl}`,
|
|
13
|
+
`公开链接: https://www.xiaohongshu.com/explore/${noteId}`,
|
|
14
|
+
];
|
|
15
|
+
if (detail.coverImage) {
|
|
16
|
+
lines.push(`封面: ${detail.coverImage}`);
|
|
17
|
+
}
|
|
18
|
+
if (detail.tags.length > 0) {
|
|
19
|
+
lines.push(`标签: ${detail.tags.join('、')}`);
|
|
20
|
+
}
|
|
21
|
+
lines.push('', '正文:', detail.content || '(空)');
|
|
22
|
+
return lines.join('\n');
|
|
23
|
+
}
|
|
24
|
+
async function getNoteDetailById(page, noteId) {
|
|
25
|
+
const editUrl = `https://creator.xiaohongshu.com/publish/update?id=${noteId}`;
|
|
26
|
+
await page.goto(editUrl, { waitUntil: 'domcontentloaded', timeout: 30000 });
|
|
27
|
+
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
28
|
+
const currentUrl = page.url();
|
|
29
|
+
if (currentUrl.includes('/login') || currentUrl.includes('/signin')) {
|
|
30
|
+
throw new Error('需要登录才能查看笔记详情');
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
await page.waitForSelector('input.d-text, .tiptap.ProseMirror', { timeout: 10000 });
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
console.warn('⚠️ 等待元素超时,继续尝试提取...');
|
|
37
|
+
}
|
|
38
|
+
const detail = await page.evaluate(() => {
|
|
39
|
+
const titleInput = document.querySelector('input.d-text');
|
|
40
|
+
const contentEl = document.querySelector('.tiptap.ProseMirror');
|
|
41
|
+
const tags = [];
|
|
42
|
+
const tagSet = new Set();
|
|
43
|
+
document.querySelectorAll('a.tiptap-topic').forEach((topicEl) => {
|
|
44
|
+
let tagName = '';
|
|
45
|
+
const dataTopic = topicEl.getAttribute('data-topic');
|
|
46
|
+
if (dataTopic) {
|
|
47
|
+
try {
|
|
48
|
+
const topicData = JSON.parse(dataTopic);
|
|
49
|
+
tagName = (topicData.name ?? '').trim();
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
tagName = (topicEl.textContent ?? '').trim().replace(/#/g, '').replace(/\[话题\]/g, '').trim();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
tagName = (topicEl.textContent ?? '').trim().replace(/#/g, '').replace(/\[话题\]/g, '').trim();
|
|
57
|
+
}
|
|
58
|
+
if (tagName && !tagSet.has(tagName)) {
|
|
59
|
+
tagSet.add(tagName);
|
|
60
|
+
tags.push(tagName);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
const coverEl = document.querySelector('.cover img, .note-cover img, [class*="cover"] img, .preview img');
|
|
64
|
+
const timeEl = document.querySelector('.publish-time, .time, [class*="time"], [class*="date"]');
|
|
65
|
+
return {
|
|
66
|
+
title: (titleInput?.value ?? '').trim(),
|
|
67
|
+
content: (contentEl?.textContent ?? '').trim(),
|
|
68
|
+
tags,
|
|
69
|
+
publishTime: (timeEl?.textContent ?? '').trim(),
|
|
70
|
+
coverImage: coverEl?.src ?? '',
|
|
71
|
+
editorUrl: window.location.href,
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
if (!detail.title && !detail.content) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
return detail;
|
|
78
|
+
}
|
|
79
|
+
export async function getNoteDetail(noteId, session) {
|
|
80
|
+
const id = normalizeNoteId(noteId);
|
|
81
|
+
if (!id) {
|
|
82
|
+
throw new Error('noteId 不能为空');
|
|
83
|
+
}
|
|
84
|
+
const cacheFilename = prefixedCacheFilename(session.cachePathPrefix, `notes/${id}_detail_text.json`);
|
|
85
|
+
const cached = loadFromCache(cacheFilename);
|
|
86
|
+
if (cached?.text?.trim()) {
|
|
87
|
+
return cached.text;
|
|
88
|
+
}
|
|
89
|
+
const detail = await withLoggedInPage(async (page) => getNoteDetailById(page, id), session.browserUserDataDir);
|
|
90
|
+
if (!detail) {
|
|
91
|
+
return `未找到笔记详情: ${id}`;
|
|
92
|
+
}
|
|
93
|
+
const text = formatNoteDetail(id, detail);
|
|
94
|
+
saveToCache(cacheFilename, {
|
|
95
|
+
text,
|
|
96
|
+
updatedAt: new Date().toISOString(),
|
|
97
|
+
});
|
|
98
|
+
return text;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=get_note_detail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_note_detail.js","sourceRoot":"","sources":["../../src/toolset/get_note_detail.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Page } from 'puppeteer-core';
|
|
2
|
+
export interface UserProfile {
|
|
3
|
+
accountName: string;
|
|
4
|
+
followingCount: string;
|
|
5
|
+
fansCount: string;
|
|
6
|
+
likesAndCollects: string;
|
|
7
|
+
xhsAccountId: string;
|
|
8
|
+
description: string;
|
|
9
|
+
accountStatus: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function validateUserProfile(profile: UserProfile | null): profile is UserProfile;
|
|
12
|
+
/** 供登录成功提示、toolImplementations 等复用 */
|
|
13
|
+
export declare function formatUserProfileText(profile: UserProfile): string;
|
|
14
|
+
/** 在当前页抓取用户资料(供 login 等复用) */
|
|
15
|
+
export declare function getUserProfile(page: Page): Promise<UserProfile>;
|
|
16
|
+
//# sourceMappingURL=get_profile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_profile.d.ts","sourceRoot":"","sources":["../../src/toolset/get_profile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,IAAI,WAAW,CAQvF;AAED,sCAAsC;AACtC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAQlE;AAED,8BAA8B;AAC9B,wBAAsB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAwDrE"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// 核心功能:获取用户资料(页面抓取为结构化字段;对外汇总接口返回纯文本)
|
|
2
|
+
export function validateUserProfile(profile) {
|
|
3
|
+
if (!profile || typeof profile !== 'object') {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
if (!profile.accountName && !profile.fansCount && !profile.followingCount) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
/** 供登录成功提示、toolImplementations 等复用 */
|
|
12
|
+
export function formatUserProfileText(profile) {
|
|
13
|
+
return [
|
|
14
|
+
`昵称: ${profile.accountName || '—'}`,
|
|
15
|
+
`状态: ${profile.accountStatus || '—'}`,
|
|
16
|
+
`关注: ${profile.followingCount} 粉丝: ${profile.fansCount} 获赞与收藏: ${profile.likesAndCollects}`,
|
|
17
|
+
`小红书账号: ${profile.xhsAccountId || '—'}`,
|
|
18
|
+
profile.description ? `简介: ${profile.description}` : '简介: —',
|
|
19
|
+
].join('\n');
|
|
20
|
+
}
|
|
21
|
+
/** 在当前页抓取用户资料(供 login 等复用) */
|
|
22
|
+
export async function getUserProfile(page) {
|
|
23
|
+
await page.goto('https://creator.xiaohongshu.com/new/home', {
|
|
24
|
+
waitUntil: 'domcontentloaded',
|
|
25
|
+
timeout: 30000,
|
|
26
|
+
});
|
|
27
|
+
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
28
|
+
const profile = await page.evaluate(() => {
|
|
29
|
+
const p = {
|
|
30
|
+
accountName: '',
|
|
31
|
+
followingCount: '0',
|
|
32
|
+
fansCount: '0',
|
|
33
|
+
likesAndCollects: '0',
|
|
34
|
+
xhsAccountId: '',
|
|
35
|
+
description: '',
|
|
36
|
+
accountStatus: '',
|
|
37
|
+
};
|
|
38
|
+
const accountNameEl = document.querySelector('.account-name');
|
|
39
|
+
if (accountNameEl) {
|
|
40
|
+
p.accountName = (accountNameEl.textContent || '').trim();
|
|
41
|
+
}
|
|
42
|
+
const statusImg = document.querySelector('img[alt="account-status"]');
|
|
43
|
+
if (statusImg) {
|
|
44
|
+
p.accountStatus = statusImg.getAttribute('alt') || '';
|
|
45
|
+
}
|
|
46
|
+
const numericalEls = document.querySelectorAll('.numerical');
|
|
47
|
+
if (numericalEls.length >= 3) {
|
|
48
|
+
p.followingCount = (numericalEls[0].textContent || '').trim();
|
|
49
|
+
p.fansCount = (numericalEls[1].textContent || '').trim();
|
|
50
|
+
p.likesAndCollects = (numericalEls[2].textContent || '').trim();
|
|
51
|
+
}
|
|
52
|
+
const othersContainer = document.querySelector('.others.description-text');
|
|
53
|
+
if (othersContainer) {
|
|
54
|
+
const children = othersContainer.children;
|
|
55
|
+
if (children.length > 0) {
|
|
56
|
+
const accountText = (children[0].textContent || '').trim();
|
|
57
|
+
if (accountText.includes('小红书账号:')) {
|
|
58
|
+
p.xhsAccountId = accountText.replace('小红书账号:', '').trim();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (children.length > 2) {
|
|
62
|
+
p.description = (children[2].textContent || '').trim();
|
|
63
|
+
}
|
|
64
|
+
if (!p.xhsAccountId) {
|
|
65
|
+
const allText = othersContainer.textContent || '';
|
|
66
|
+
const accountMatch = allText.match(/小红书账号:\s*(\d+)/);
|
|
67
|
+
if (accountMatch) {
|
|
68
|
+
p.xhsAccountId = accountMatch[1];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return p;
|
|
73
|
+
});
|
|
74
|
+
if (!validateUserProfile(profile)) {
|
|
75
|
+
throw new Error('获取用户资料失败:页面元素未正确加载,请稍后重试');
|
|
76
|
+
}
|
|
77
|
+
return profile;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=get_profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_profile.js","sourceRoot":"","sources":["../../src/toolset/get_profile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_recent_posts.d.ts","sourceRoot":"","sources":["../../src/toolset/get_recent_posts.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAyHzD,wBAAsB,cAAc,CAClC,OAAO,EAAE,eAAe,EACxB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAEjB"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { withLoggedInPage } from '../browser/index.js';
|
|
2
|
+
import { saveToCache, loadFromCache } from '../utils/cache.js';
|
|
3
|
+
import { prefixedCacheFilename } from './cachePaths.js';
|
|
4
|
+
function formatNote(note) {
|
|
5
|
+
return [
|
|
6
|
+
`ID: ${note.noteId}`,
|
|
7
|
+
`标题: ${note.title}`,
|
|
8
|
+
`发布时间: ${note.publishTime}`,
|
|
9
|
+
`链接: ${note.url}`,
|
|
10
|
+
`浏览: ${note.views} 点赞: ${note.likes} 评论: ${note.comments} 收藏: ${note.favorites} 分享: ${note.shares}`,
|
|
11
|
+
].join('\n');
|
|
12
|
+
}
|
|
13
|
+
async function getInteractionCount(page, card, type) {
|
|
14
|
+
const iconList = await card.$('.icon_list');
|
|
15
|
+
if (!iconList)
|
|
16
|
+
return '0';
|
|
17
|
+
const icons = await iconList.$$('.icon');
|
|
18
|
+
for (const icon of icons) {
|
|
19
|
+
const iconText = await page.evaluate((el, targetType) => {
|
|
20
|
+
const d = el.querySelector('svg path')?.getAttribute('d') ?? '';
|
|
21
|
+
const count = (el.querySelector('span')?.textContent ?? '').trim();
|
|
22
|
+
if (targetType === 'views' && (d.includes('M21.83 11.442') || d.includes('M15 12')))
|
|
23
|
+
return count;
|
|
24
|
+
if (targetType === 'likes' && (d.includes('M12 22c5.5 0') || d.includes('M8.4 11')))
|
|
25
|
+
return count;
|
|
26
|
+
if (targetType === 'favorites' && (d.includes('M12 4.32A6.19') || d.includes('l7.244 7.17')))
|
|
27
|
+
return count;
|
|
28
|
+
if (targetType === 'comments' && (d.includes('M5.873 21.142') || d.includes('l.469-4.549')))
|
|
29
|
+
return count;
|
|
30
|
+
if (targetType === 'shares' && (d.includes('M20.673 12.764') || d.includes('l-8.612-6.236')))
|
|
31
|
+
return count;
|
|
32
|
+
return null;
|
|
33
|
+
}, icon, type);
|
|
34
|
+
if (iconText)
|
|
35
|
+
return iconText;
|
|
36
|
+
}
|
|
37
|
+
return '0';
|
|
38
|
+
}
|
|
39
|
+
async function scrapeRecentPosts(page, session, limit) {
|
|
40
|
+
await page.goto('https://creator.xiaohongshu.com/new/note-manager', {
|
|
41
|
+
waitUntil: 'domcontentloaded',
|
|
42
|
+
timeout: 30000,
|
|
43
|
+
});
|
|
44
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
45
|
+
const noteCards = await page.$$('div.note');
|
|
46
|
+
const results = [];
|
|
47
|
+
for (const card of noteCards) {
|
|
48
|
+
if (typeof limit === 'number' && results.length >= limit)
|
|
49
|
+
break;
|
|
50
|
+
const impressionData = await page.evaluate((el) => {
|
|
51
|
+
const raw = el.getAttribute('data-impression');
|
|
52
|
+
if (!raw)
|
|
53
|
+
return null;
|
|
54
|
+
try {
|
|
55
|
+
return JSON.parse(raw);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}, card);
|
|
61
|
+
const noteId = impressionData?.noteTarget?.value?.noteId ?? '';
|
|
62
|
+
if (!noteId)
|
|
63
|
+
continue;
|
|
64
|
+
const cacheKey = prefixedCacheFilename(session.cachePathPrefix, `notes/${noteId}.json`);
|
|
65
|
+
const cached = loadFromCache(cacheKey);
|
|
66
|
+
const views = await getInteractionCount(page, card, 'views');
|
|
67
|
+
const likes = await getInteractionCount(page, card, 'likes');
|
|
68
|
+
const comments = await getInteractionCount(page, card, 'comments');
|
|
69
|
+
const favorites = await getInteractionCount(page, card, 'favorites');
|
|
70
|
+
const shares = await getInteractionCount(page, card, 'shares');
|
|
71
|
+
let note;
|
|
72
|
+
if (cached) {
|
|
73
|
+
note = { ...cached, views, likes, comments, favorites, shares };
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const titleEl = await card.$('.info .title');
|
|
77
|
+
const title = titleEl ? await page.evaluate((el) => (el.textContent ?? '').trim(), titleEl) : '未知标题';
|
|
78
|
+
const timeEl = await card.$('.info .time');
|
|
79
|
+
const publishTime = timeEl ? await page.evaluate((el) => (el.textContent ?? '').trim(), timeEl) : '';
|
|
80
|
+
let coverImage = '';
|
|
81
|
+
const imgEl = await card.$('.img img');
|
|
82
|
+
if (imgEl) {
|
|
83
|
+
coverImage = await page.evaluate((el) => el.getAttribute('src') ?? '', imgEl);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const bgEl = await card.$('.img .media-bg');
|
|
87
|
+
if (bgEl) {
|
|
88
|
+
const style = await page.evaluate((el) => el.getAttribute('style') ?? '', bgEl);
|
|
89
|
+
const urlMatch = style.match(/url\(["']?([^"']+)["']?\)/);
|
|
90
|
+
if (urlMatch)
|
|
91
|
+
coverImage = urlMatch[1];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
note = {
|
|
95
|
+
noteId,
|
|
96
|
+
title,
|
|
97
|
+
publishTime,
|
|
98
|
+
url: `https://www.xiaohongshu.com/explore/${noteId}`,
|
|
99
|
+
views, likes, comments, favorites, shares,
|
|
100
|
+
coverImage,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
saveToCache(cacheKey, note);
|
|
104
|
+
results.push(note);
|
|
105
|
+
}
|
|
106
|
+
if (results.length === 0)
|
|
107
|
+
return '未找到笔记数据';
|
|
108
|
+
return results.map(formatNote).join('\n\n');
|
|
109
|
+
}
|
|
110
|
+
export async function getRecentPosts(session, limit) {
|
|
111
|
+
return withLoggedInPage((page) => scrapeRecentPosts(page, session, limit), session.browserUserDataDir);
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=get_recent_posts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_recent_posts.js","sourceRoot":"","sources":["../../src/toolset/get_recent_posts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type PostNoteArgs } from './post.js';
|
|
2
|
+
import { resolveAccountSlug, resolveSession } from './sessionResolve.js';
|
|
3
|
+
import type { ResolvedSession } from './sessionTypes.js';
|
|
4
|
+
export declare function implLogin(session?: ResolvedSession): Promise<string>;
|
|
5
|
+
export declare function implGetOperationData(session?: ResolvedSession): Promise<string>;
|
|
6
|
+
export declare function implPosted(limit: number | undefined, session?: ResolvedSession): Promise<string>;
|
|
7
|
+
export declare function implGetNoteDetail(noteId: string, session?: ResolvedSession): Promise<string>;
|
|
8
|
+
export declare function implPost(args: PostNoteArgs): Promise<string>;
|
|
9
|
+
export { resolveAccountSlug, resolveSession };
|
|
10
|
+
export { setCurrentAccount, getCurrentAccount } from './accountRegistry.js';
|
|
11
|
+
export type { ResolvedSession };
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/toolset/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAY,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AASzD,wBAAsB,SAAS,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAO1E;AAED,wBAAsB,oBAAoB,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAGrF;AAED,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAOlE;AAED,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,YAAY,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 小红书等业务能力(impl*);供 CLI 子命令直接调用;外部 Agent 可单独引用同一套 impl。
|
|
3
|
+
*/
|
|
4
|
+
import { login } from './login.js';
|
|
5
|
+
import { getOperationData } from './get_metrics.js';
|
|
6
|
+
import { getNoteDetail } from './get_note_detail.js';
|
|
7
|
+
import { formatUserProfileText } from './get_profile.js';
|
|
8
|
+
import { getRecentPosts } from './get_recent_posts.js';
|
|
9
|
+
import { postNote } from './post.js';
|
|
10
|
+
import { resolveAccountSlug, resolveSession } from './sessionResolve.js';
|
|
11
|
+
function sessionOrDefault(session) {
|
|
12
|
+
if (session) {
|
|
13
|
+
return session;
|
|
14
|
+
}
|
|
15
|
+
return resolveSession();
|
|
16
|
+
}
|
|
17
|
+
export async function implLogin(session) {
|
|
18
|
+
const s = sessionOrDefault(session);
|
|
19
|
+
const userProfile = await login(s.browserUserDataDir);
|
|
20
|
+
if (userProfile) {
|
|
21
|
+
return `✅ 登录成功\n${formatUserProfileText(userProfile)}`;
|
|
22
|
+
}
|
|
23
|
+
return '❌ 登录失败';
|
|
24
|
+
}
|
|
25
|
+
export async function implGetOperationData(session) {
|
|
26
|
+
const s = sessionOrDefault(session);
|
|
27
|
+
return getOperationData(s);
|
|
28
|
+
}
|
|
29
|
+
export async function implPosted(limit, session) {
|
|
30
|
+
const s = sessionOrDefault(session);
|
|
31
|
+
return getRecentPosts(s, limit);
|
|
32
|
+
}
|
|
33
|
+
export async function implGetNoteDetail(noteId, session) {
|
|
34
|
+
const s = sessionOrDefault(session);
|
|
35
|
+
return getNoteDetail(noteId, s);
|
|
36
|
+
}
|
|
37
|
+
export async function implPost(args) {
|
|
38
|
+
try {
|
|
39
|
+
const result = await postNote(args);
|
|
40
|
+
return result.success ? `✅ ${result.message}` : `❌ ${result.message}`;
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
return `❌ ${e instanceof Error ? e.message : String(e)}`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export { resolveAccountSlug, resolveSession };
|
|
47
|
+
export { setCurrentAccount, getCurrentAccount } from './accountRegistry.js';
|
|
48
|
+
//# sourceMappingURL=index.js.map
|