refactor: remove xiaohongshu me, add lessons learned, fix docs
- Remove xiaohongshu/me (profile page async loading too unreliable) - CLI-CREATOR: add 4 lessons to 常见陷阱 (stale dist YAML, TS IIFE format, async polling, YAML vs TS threshold) - Fix build: clean-yaml before copy to prevent stale overrides - Fix docs: MCP token is configured via MCP config, not env var - Update all command lists (README, README.zh-CN, SKILL.md)
This commit is contained in:
1 parent
fd94a5d27b
commit
999d340a34
7 files changed
+10
-49
No files matched your search
@@ -571,6 +571,9 @@ git push
|
||||
| 搜索参数被 URL 编码 | `${{ args.keyword }}` 被浏览器二次编码 | 在 evaluate 内用 `encodeURIComponent()` 手动编码 |
|
||||
| Cookie 过期 | 返回 401 / 空数据 | 在浏览器里重新登录目标站点 |
|
||||
| Extension tab 残留 | Chrome 多出 `chrome-extension://` tab | 已自动清理;若残留,手动关闭即可 |
|
||||
| TS evaluate 格式 | `() => {}` 报 `result is not a function` | TS 中 `page.evaluate()` 必须用 IIFE:`(async () => { ... })()` |
|
||||
| 页面异步加载 | evaluate 拿到空数据(store state 还没更新) | 在 evaluate 内用 polling 等待数据出现,或增加 `wait` 时间 |
|
||||
| YAML 内嵌大段 JS | 调试困难,字符串转义问题 | 超过 10 行 JS 的命令改用 TS adapter |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ npm install -g @jackwener/opencli@latest
|
||||
Browser commands need:
|
||||
1. **Chrome** running **and logged into the target site** (e.g. bilibili.com, zhihu.com, xiaohongshu.com)
|
||||
2. **[Playwright MCP Bridge](https://chromewebstore.google.com/detail/playwright-mcp-bridge/mmlmfjhmonkocbjadbfplnigmagldckm)** extension installed
|
||||
3. Configure `PLAYWRIGHT_MCP_EXTENSION_TOKEN` (from the extension settings page) as an environment variable, or in your MCP config:
|
||||
3. Configure `PLAYWRIGHT_MCP_EXTENSION_TOKEN` (from the extension settings page) in your MCP config:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -83,7 +83,7 @@ Public API commands (`hackernews`, `github search`, `v2ex`) need no browser at a
|
||||
|------|----------|------|
|
||||
| **bilibili** | `hot` `search` `me` `favorite` `history` `feed` `user-videos` | 🔐 Browser |
|
||||
| **zhihu** | `hot` `search` `question` | 🔐 Browser |
|
||||
| **xiaohongshu** | `search` `me` `notifications` `feed` | 🔐 Browser |
|
||||
| **xiaohongshu** | `search` `notifications` `feed` | 🔐 Browser |
|
||||
| **twitter** | `trending` | 🔐 Browser |
|
||||
| **reddit** | `hot` | 🔐 Browser |
|
||||
| **github** | `trending` `search` | 🔐 / 🌐 |
|
||||
|
||||
+2
-2
@@ -57,7 +57,7 @@ npm install -g @jackwener/opencli@latest
|
||||
浏览器命令需要:
|
||||
1. **Chrome** 浏览器正在运行,且**已登录目标网站**(如 bilibili.com、zhihu.com、xiaohongshu.com)
|
||||
2. 安装 **[Playwright MCP Bridge](https://chromewebstore.google.com/detail/playwright-mcp-bridge/mmlmfjhmonkocbjadbfplnigmagldckm)** 扩展
|
||||
3. 配置 `PLAYWRIGHT_MCP_EXTENSION_TOKEN`(从扩展设置页获取),设为环境变量或写入 MCP 配置:
|
||||
3. 在 MCP 配置中设置 `PLAYWRIGHT_MCP_EXTENSION_TOKEN`(从扩展设置页获取):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -83,7 +83,7 @@ npm install -g @jackwener/opencli@latest
|
||||
|------|------|------|
|
||||
| **bilibili** | `hot` `search` `me` `favorite` `history` `feed` `user-videos` | 🔐 浏览器 |
|
||||
| **zhihu** | `hot` `search` `question` | 🔐 浏览器 |
|
||||
| **xiaohongshu** | `search` `me` `notifications` `feed` | 🔐 浏览器 |
|
||||
| **xiaohongshu** | `search` `notifications` `feed` | 🔐 浏览器 |
|
||||
| **twitter** | `trending` | 🔐 浏览器 |
|
||||
| **reddit** | `hot` | 🔐 浏览器 |
|
||||
| **github** | `trending` `search` | 🔐 / 🌐 |
|
||||
|
||||
@@ -30,7 +30,7 @@ npm update -g @jackwener/opencli
|
||||
Browser commands require:
|
||||
1. Chrome browser running **(logged into target sites)**
|
||||
2. [Playwright MCP Bridge](https://chromewebstore.google.com/detail/playwright-mcp-bridge/mmlmfjhmonkocbjadbfplnigmagldckm) extension
|
||||
3. Configure `PLAYWRIGHT_MCP_EXTENSION_TOKEN` env var (from extension settings) or in MCP config
|
||||
3. Configure `PLAYWRIGHT_MCP_EXTENSION_TOKEN` (from extension settings) in your MCP config
|
||||
|
||||
> **Note**: You must be logged into the target website in Chrome before running commands. Tabs opened during command execution are auto-closed afterwards.
|
||||
|
||||
@@ -57,7 +57,6 @@ opencli zhihu question --id 34816524 # 问题详情和回答
|
||||
|
||||
# 小红书 (browser)
|
||||
opencli xiaohongshu search --keyword "美食" # 搜索笔记
|
||||
opencli xiaohongshu me # 我的信息
|
||||
opencli xiaohongshu notifications # 通知(mentions/likes/connections)
|
||||
opencli xiaohongshu feed --limit 10 # 推荐 Feed
|
||||
|
||||
|
||||
+2
-1
@@ -12,7 +12,8 @@
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "tsx src/main.ts",
|
||||
"build": "tsc && npm run copy-yaml",
|
||||
"build": "tsc && npm run clean-yaml && npm run copy-yaml",
|
||||
"clean-yaml": "find dist/clis -name '*.yaml' -o -name '*.yml' 2>/dev/null | xargs rm -f",
|
||||
"copy-yaml": "find src/clis -name '*.yaml' -o -name '*.yml' | while read f; do d=\"dist/${f#src/}\"; mkdir -p \"$(dirname \"$d\")\"; cp \"$f\" \"$d\"; done",
|
||||
"start": "node dist/main.js",
|
||||
"typecheck": "tsc --noEmit",
|
||||
|
||||
@@ -20,4 +20,3 @@ import './zhihu/question.js';
|
||||
|
||||
// xiaohongshu
|
||||
import './xiaohongshu/search.js';
|
||||
import './xiaohongshu/me.js';
|
||||
@@ -1,41 +0,0 @@
|
||||
/**
|
||||
* Xiaohongshu me — read self profile info from Pinia user store.
|
||||
*/
|
||||
import { cli, Strategy } from '../../registry.js';
|
||||
|
||||
cli({
|
||||
site: 'xiaohongshu',
|
||||
name: 'me',
|
||||
description: '我的小红书个人信息',
|
||||
domain: 'www.xiaohongshu.com',
|
||||
strategy: Strategy.COOKIE,
|
||||
args: [],
|
||||
columns: ['nickname', 'red_id', 'fans', 'follows', 'notes', 'likes_collected'],
|
||||
func: async (page) => {
|
||||
await page.goto('https://www.xiaohongshu.com/user/profile/self');
|
||||
await page.wait(3);
|
||||
|
||||
const data = await page.evaluate(`
|
||||
(() => {
|
||||
const app = document.querySelector('#app')?.__vue_app__;
|
||||
const pinia = app?.config?.globalProperties?.$pinia;
|
||||
if (!pinia?._s) return { error: 'Page not ready' };
|
||||
const userStore = pinia._s.get('user');
|
||||
if (!userStore) return { error: 'User store not found' };
|
||||
const state = userStore.$state || {};
|
||||
const u = state.selfInfo || state.currentUserInfo || state.userInfo || {};
|
||||
return {
|
||||
nickname: u.nickname || u.name || '',
|
||||
red_id: u.red_id || u.redId || '',
|
||||
fans: u.fans || u.fansCount || 0,
|
||||
follows: u.follows || u.followsCount || 0,
|
||||
notes: u.notes || u.noteCount || 0,
|
||||
likes_collected: u.collected || u.likedAndCollected || 0,
|
||||
};
|
||||
})()
|
||||
`);
|
||||
|
||||
if (!data || data.error) return [];
|
||||
return [data];
|
||||
},
|
||||
});
|
||||
Reference in new issue
Block a user