--- id: QuZhan51496/paper2anything/paper2xhs version: "290c0c9c" license: Apache-2.0 install: manual updated: 2026-07-16 --- # paper2xhs — paper2xhs transforms academic PDFs into Xiaohongshu multi-image posts where you drive the creative work. You read the paper, write the caption and title, pick key figures, and the skill handles PDF parsing, cover generation (via API or local fallback), and optional publishing to Xiaohongshu. Publisher: QuZhan51496 · Stars: 304 · Updated: 2026-07-16 Install (manual): `git clone https://github.com/QuZhan51496/paper2anything` ## SKILL.md # paper2xhs — 论文转小红书(你主导的协调式) 把一篇论文 PDF 转成小红书帖子。**你是主笔**:这份文件是配方,不是全自动脚本—— 没有 `main.py`。机械步骤(解析 / 封面 / 发布)调用 `scripts/` 下的小工具;**论文理解、 选题角度、文案撰写由你亲自完成**(用 Read 看材料、用 Write 落产物),并在关键点用 `AskUserQuestion` 与用户确认。 ```text PDF → 解析 (parse_pdf.py:MinerU → parsed/ + figures/) → 你读懂论文 (读 parsed/ + 看 figures/) → understanding/paper_understanding.json [确认选题角度] → 你写小红书文案 (标题/正文/标签/封面文字) → xhs_post.json + xhs_post.md [确认文案] → 封面+配图 (cover.py 封面:默认 API 生图 gpt-image-2、无 key 回退本地合成; post_images.py 配图:把你选的论文主图/主实验图按序复制成图集,原图直出) → 半自动发布 (publish.py:封面+配图多图帖,可选) → 小红书帖子 ``` ## 运行方式 1. **一步步来**:机械步骤用 `Bash` 调脚本,创作步骤你自己用 `Read` / `Write` 做。不要试图一条命令跑完。 2. **每个 Bash 块开头就地算 `WORKDIR`**——各 Bash 调用是独立 shell、不共享变量,所以别指望 `export` 跨步存活: ```bash WORKDIR="$(dirname "$pdf_path")/.paper2anything/xhs/$(basename "${pdf_path%.*}")" ``` 其中 `$pdf_path` 是用户给的论文 PDF 路径(每个块都重新设一次)。脚本在 `${SKILL_DIR}/scripts`——`SKILL_DIR` 是**本 skill 的目录**(见本 skill 顶部注入的 "Base directory for this skill: …");各 Bash 块独立 shell, 用到它的块开头按需 `export SKILL_DIR=<那个目录>` 一次(和 `WORKDIR` 一样每块现设)。 3. **在两个决策点用 `AskUserQuestion` 暂停**:① 读懂论文后确认“选题角度”;② 文案成稿后确认。用户想改,可直接改产物 JSON/MD 或告诉你改。 4. **小红书是“准确、不夸大的科普”**:忠实反映论文贡献,口语化、有钩子,但**绝不编造数据或夸大结论**。 --- ## Step 0:环境与凭据 > **统一环境**:所有 `python` 命令都在 paper2anything 的统一 conda 环境里(顶层 `environment.yml` 创建),命令以 `conda run -n paper2anything --no-capture-output` 为前缀。 凭据集中在 paper2anything 包根的 `.env`(从 `.env.example` 复制,已 gitignore)。每个新 shell 先导出一次: ```bash set -a; source /.env; set +a ``` 本 skill 用到的 key(**理解与文案由你亲自做,不调用任何 LLM API**): - `MINERU_API_TOKEN` — 解析 PDF(必填) - `OPENAI_API_KEY`(+ `OPENAI_BASE_URL`) — 封面默认走它生图(gpt-image-2);无 key 或 key 不可用时回退本地合成(复用论文原图) - `XHS_MCP_BIN` — 可选:自定义 [xiaohongshu-mcp](https://github.com/xpzouying/xiaohongshu-mcp) 二进制位置;**不设则发布时 skill 自动按平台下载**到 `~/.paper2anything/xhs/`。另可选 `XHS_MCP_URL`(自定义服务地址/端口,默认 `http://localhost:18060`)。 依赖自检(缺啥按提示装;依赖统一在 `environment.yml`): ```bash conda run -n paper2anything --no-capture-output python -c "import requests, rich, dotenv" 2>&1 ``` --- ## Step 1:解析 PDF(脚本) ```bash pdf_path="/path/to/paper.pdf" # ← 用户的论文 PDF WORKDIR="$(dirname "$pdf_path")/.paper2anything/xhs/$(basename "${pdf_path%.*}")" conda run -n paper2anything --no-capture-output \ python "${SKILL_DIR}/scripts/parse_pdf.py" "$pdf_path" --workdir "$WORKDIR" ``` 产出(`$WORKDIR` 下): - `parsed/paper_meta.json`(title / authors / abstract)、`parsed/sections.json`(`[{title, content}]`)、`parsed/figures_index.json`(`[{figure_id, caption, image_path, page}]`,`image_path` 已指向 `figures/` 实体)、`parsed/references.json` - `figures/*` 论文插图实体 解析完,先 `Read` `parsed/sections.json` 与 `parsed/paper_meta.json` 通读全文。 --- ## Step 2:读懂论文 → 写 understanding(你来做)[确认] 这是创作的地基,**你自己做判断**,不要交给脚本: 1. `Read` `parsed/sections.json`(全文)+ `parsed/paper_meta.json`;`Read` `parsed/figures_index.json` 看图注(个别图 caption 可能为空;多面板大图可能被解析器拆成两半、完整图注只挂在其中一半上,且拆缝处图例/轴标签可能被裁——一律以实际看图为准),并**实际 `Read` 几张候选图片**(`figures/` 下)判断哪些清晰、适合做封面或配图——图注说“framework”的图在小图里未必好看,只有你的眼睛能判断。 2. 用 `Write` 落 `understanding/paper_understanding.json`,schema: ```json { "paper_title": "...", "method_name": "方法简称(如 AccKV)", "one_sentence_summary": "一句话讲清这篇做了什么", "problem": "解决什么问题", "method": "怎么做的", "highlights": ["有数据支撑的亮点1", "创新点2", "应用价值3"], "experiment_results": ["关键数据1(含数字)", "..."], "keywords": ["领域关键词", "..."], "cover_palette": {"bg": "#F4F5F7", "accent": "#2E86AB"}, "important_figures": [ {"figure_id": "fig_1", "image_path": "", "suitable_for_cover": true, "importance_score": 0.9, "description": "图说明"} ], "post_figures": [ {"image_path": ""} ] } ``` - `important_figures` 必须含 `image_path`(取自 `parsed/figures_index.json`,指向真实存在的图)、`suitable_for_cover`、`importance_score`——封面默认走 API 生图(gpt-image-2),仅当 `OPENAI_API_KEY` 未配/不可用时回退本地合成、靠这几个字段复用原图;漏了则回退时无图 → 封面 `skipped`。 - `post_figures`(多图帖正文配图,建议 2~4 张、按展示顺序排):**第一张放论文主图**(框架/方法总览), 其后放**主实验结果图**;只放你亲眼 `Read` 过、缩到手机宽度仍清晰可读的图。配图**原图直出、 不做任何加工**。发布时图集 = 封面 + 这些配图。 - `cover_palette`(可选):本地合成回退路径的配色,按论文领域选 `bg`(浅色打底) + `accent`(强调色),标题字色会随底色深浅自动适配。参考浅色调:通用 `#F4F5F7`+`#2E86AB`、生物 `#EEF6F0`+`#2D8A5F`、物理数学 `#F1ECF8`+`#6A30C2`、工程 `#FBF0EC`+`#D85A3C`、社科 `#F4EEF2`+`#8A5A78`、化学 `#EAF4F8`+`#0E86C0`。 3. 用 `AskUserQuestion` 与用户确认**选题角度**:这篇论文发小红书主打哪个亮点 / 用什么钩子 / 面向哪类读者。带着确认结果再写文案。 --- ## Step 3:写小红书帖子(你来做)[确认] 按小红书风格**亲自撰写**,用 `Write` 落 `xhs_post.json` 和 `xhs_post.md`。 **小红书文案规则(领域知识):** - **标题** ≤20 字,吸睛:含核心价值、或数字、或对比、或悬念式提问。 - **正文 300–600 字**,结构: 1. 开头 1–2 句钩子,抓住注意力 2. 这篇论文是什么、解决什么问题(2–3 句) 3. 3–5 个核心亮点,每点用 emoji 开头,简洁有力 4. 1–3 个关键实验数据,要具体 5. 对读者有什么用(1–2 句) 6. 结尾引导互动(如“你觉得这方法能用在哪?”) - **风格**:口语化、易读、不端学术腔,但**忠实准确、不夸大、不编数据**。 - **标签** 8–12 个,写在正文末尾;`hashtags` 字段同步放这些标签(发布脚本读 `hashtags`)。 - **封面文字** `cover_text` ≤15 字(封面大字用)。 产物 schema —— `xhs_post.json`: ```json {"title": "...", "body": "含 emoji/换行,末尾带标签的完整正文", "hashtags": ["#标签1", "#标签2"], "cover_text": "≤15字封面词", "paper_title_zh": "论文中文标题"} ``` `xhs_post.md`:第一行 `# {title}`,然后正文;可在顶部放 `![封面](cover.png)` 占位(封面在 Step 4 生成)。 写完用 `AskUserQuestion` 给用户看标题 + 正文摘要,确认或按反馈修改(可直接改 JSON/MD)。 --- ## Step 4:生成封面与配图(脚本,可选) **封面主/副标题此刻由你现拟**(你已读透论文,比从 JSON 里捡更贴切),经 `--title`(主标题大字)/ `--subtitle`(副标题小字)传入: ```bash pdf_path="/path/to/paper.pdf" WORKDIR="$(dirname "$pdf_path")/.paper2anything/xhs/$(basename "${pdf_path%.*}")" conda run -n paper2anything --no-capture-output \ python "${SKILL_DIR}/scripts/cover.py" --workdir "$WORKDIR" \ --title "你拟的封面主标题大字" --subtitle "你拟的副标题小字" ``` 逻辑:**默认用 `OPENAI_IMAGE_MODEL`(默认 `gpt-image-2`)生成竖版封面**,主标题大字用你传入的 `--title`、副标题小字用 `--subtitle`(留空才分别回退 `xhs_post.cover_text` / 论文标题);未配 `OPENAI_API_KEY` 或 key 不可用时回退本地合成——复用 `understanding.important_figures` 里 `suitable_for_cover` 最高分的论文原图(叠加 `--title`,配色取 `cover_palette`);两者都不可用则 `skipped`(不阻断流程)。产出 `cover.png`。 **生图 API 单次可能要好几分钟(经中转可达 6~7 分钟)**——本命令的 Bash 超时设 ≥10 分钟(600000ms),别用默认 2 分钟,超时被杀时 `logs/` 不会留 cover_result.json。 **再生成正文配图**(多图帖的第 2~N 张,纯本地排版、不调 API): ```bash conda run -n paper2anything --no-capture-output \ python "${SKILL_DIR}/scripts/post_images.py" --workdir "$WORKDIR" ``` 逻辑:读 `understanding.post_figures`,把选中的论文原图**按序直接复制**为 `post_images/p1.png|jpg…`(原图直出、不加工,后缀随原图); `understanding` 没写 `post_figures` 时回退 `important_figures` 按分前 3; 一张可用图都没有则 `skipped`(不阻断)。生成后**逐张 `Read` 亲眼确认**——图缩到手机宽度后糊、 文字不可读,就回去调 `post_figures`(换图/删图)重跑本命令(重跑会清掉旧 `p*`)。 --- ## Step 5:发布到小红书(脚本 + 你协调,可选) 发布走开源的 **[xiaohongshu-mcp](https://github.com/xpzouying/xiaohongshu-mcp)**(自带无头 Chromium 的单二进制 + REST API)。**登录一次后 cookies 持久、之后免登录**。二进制由 ① 自动备好(`XHS_MCP_BIN` 仅自定义位置时配,见 Step 0)。**首次配置/登录的分环境完整步骤见 `references/publish-guide.md`**——先 `Read` 它。不发布就跳过本步,把产物路径告诉用户手动发。 **① 确保 mcp 二进制就位并在固定持久目录运行**(二进制不存在会自动下载;cookies 落这里、跨论文复用): ```bash export XHS_MCP_DIR="$HOME/.paper2anything/xhs"; mkdir -p "$XHS_MCP_DIR" # 解析二进制:优先 .env 的 XHS_MCP_BIN;否则用持久目录里的;都没有就按平台自动下载 if [ -n "$XHS_MCP_BIN" ] && [ -x "$XHS_MCP_BIN" ]; then BIN="$XHS_MCP_BIN"; else case "$(uname -s)-$(uname -m)" in Linux-x86_64) ASSET=xiaohongshu-mcp-linux-amd64 ;; Darwin-arm64) ASSET=xiaohongshu-mcp-darwin-arm64 ;; Darwin-x86_64) ASSET=xiaohongshu-mcp-darwin-amd64 ;; *) ASSET= ; echo "未知平台,请手动下载 xiaohongshu-mcp 并在 .env 设 XHS_MCP_BIN" ;; esac BIN="$XHS_MCP_DIR/$ASSET" if [ -n "$ASSET" ] && [ ! -x "$BIN" ]; then echo "未找到 mcp 二进制,自动下载 $ASSET …" curl -fL -o "$XHS_MCP_DIR/$ASSET.tar.gz" "https://github.com/xpzouying/xiaohongshu-mcp/releases/latest/download/$ASSET.tar.gz" \ && tar xzf "$XHS_MCP_DIR/$ASSET.tar.gz" -C "$XHS_MCP_DIR" && chmod +x "$BIN" fi fi # 起服务(已在跑就跳过;BIN 不可用则报错、不硬起) if ! curl -sf http://localhost:18060/api/v1/login/status >/dev/null 2>&1; then if [ ! -x "$BIN" ]; then echo "mcp 二进制不可用($BIN)——下载失败或平台不支持,无法发布;手动下载并设 XHS_MCP_BIN,见 references/publish-guide.md" else ( cd "$XHS_MCP_DIR" && nohup "$BIN" -port=:18060 > mcp.log 2>&1 & ) for i in $(seq 1 30); do curl -sf http://localhost:18060/api/v1/login/status >/dev/null 2>&1 && break; sleep 2; done fi fi ``` (首次会下载 mcp 二进制 + 其 Chromium(约 150MB),可能要等;日志见 `$XHS_MCP_DIR/mcp.log`。macOS 若被 Gatekeeper 拦:`xattr -c "$BIN"`。) **② 查登录态**: ```bash conda run -n paper2anything --no-capture-output python "${SKILL_DIR}/scripts/publish.py" --check-only ``` `已登录` → 跳到 ④。`未登录` → 走 ③。 **③ 登录(仅首次或会话失效时)**:登录要换带界面/monitor 的方式起 mcp,**先停掉 ① 起的那个**(按进程名精确停,别用 `pkill -f`,会误杀自身): ```bash pkill -x xiaohongshu-mcp; sleep 1 ``` 再照 `references/publish-guide.md` 按环境操作。无头服务器要点:带 `-rod "monitor=:9273"` 重起 mcp(保持默认无头)→ `xhs_login.py` 取码 → `SendUserFile` 把 `qr.png` 发用户、提醒**首次可能要先在 monitor 端口(:9273)的浏览器界面里扫一道「新设备验证」码** → `AskUserQuestion` 等用户确认扫完 → 监测 cookies 写出 → 成功后**再 `pkill -x xiaohongshu-mcp` 停掉、回 ① 重启**(去掉 monitor、加载 cookies)。 ```bash conda run -n paper2anything --no-capture-output python "${SKILL_DIR}/scripts/xhs_login.py" \ --out "$XHS_MCP_DIR/qr.png" --cookies "$XHS_MCP_DIR/cookies.json" --wait ``` **④ 发布前给用户过目**:`Read` `xhs_post.json` 把**标题 + 正文**发给用户看,`SendUserFile` 发 `cover.png` 与 `post_images/` 下全部配图;用 `AskUserQuestion` 让用户**确认发布并选可见性**(选项默认「公开可见」,另有「仅自己可见」「仅互关好友可见」)。 **⑤ 发布**(传入用户选的可见性): ```bash pdf_path="/path/to/paper.pdf" WORKDIR="$(dirname "$pdf_path")/.paper2anything/xhs/$(basename "${pdf_path%.*}")" conda run -n paper2anything --no-capture-output \ python "${SKILL_DIR}/scripts/publish.py" --workdir "$WORKDIR" --visibility "公开可见" ``` 图集自动取**封面 + `post_images/` 下配图**(按 p1、p2… 排序,含封面最多 18 张)。返回「发布成功」即完成。 --- ## Step 6:把成品归集到 PDF 旁 成品默认埋在 `.paper2anything/xhs//` 里不好找。文案+封面定稿后(无论是否走 Step 5 发布),把它们复制一份 到**与 PDF 同级**的 `_xhs/` 目录(`.paper2anything` 内副本保留不动),让用户在论文旁直接取用: ```bash pdf_path="/path/to/paper.pdf" WORKDIR="$(dirname "$pdf_path")/.paper2anything/xhs/$(basename "${pdf_path%.*}")" DEST="${pdf_path%.*}_xhs" # 与 PDF 同目录、同名 + _xhs 后缀 i=2; while [ -e "$DEST" ]; do DEST="${pdf_path%.*}_xhs_v$i"; i=$((i+1)); done # 重名则追加 _v2、_v3 mkdir -p "$DEST" cp "$WORKDIR/xhs_post.md" "$WORKDIR/xhs_post.json" "$DEST/" [ -f "$WORKDIR/cover.png" ] && cp "$WORKDIR/cover.png" "$DEST/" # 封面可能 skipped,存在才复制 [ -d "$WORKDIR/post_images" ] && cp -r "$WORKDIR/post_images" "$DEST/" # 配图同理,存在才复制 ``` `xhs_post.md` 以 `![封面](cover.png)` 相对引用封面,故文案、封面与配图整组放进 `_xhs/` 子目录、引用不破。 --- ## 产物位置 中间产物落在论文旁 `/.paper2anything/xhs//`(同目录多篇论文按 `` 分篇、互不覆盖),**最终成品另复制到 PDF 同级的 `_xhs/`**(Step 6): | 路径 | 内容 | 谁写 | |---|---|---| | `.paper2anything/xhs//parsed/` | MinerU PIR(meta/sections/figures_index/references) | parse_pdf | | `.paper2anything/xhs//figures/` | 论文插图实体 | parse_pdf | | `.paper2anything/xhs//understanding/paper_understanding.json` | 论文理解 + important_figures | **你** | | `.paper2anything/xhs//xhs_post.json` `xhs_post.md` | 小红书文案 | **你** | | `.paper2anything/xhs//cover.png` | 封面 | cover | | `.paper2anything/xhs//post_images/` | 正文配图(论文原图直出 p1.png|jpg…) | post_images | | `.paper2anything/xhs//logs/` | 各脚本 `*_result.json` | 脚本 | | **`/_xhs/`** | **成品归集**:`xhs_post.md` + `.json` + `cover.png` + `post_images/`,与 PDF 同级 | **你(Step 6)** | 重跑覆盖工作区 `.paper2anything/xhs//`(中间产物);归集步骤遇同名 `_xhs/` 会另存为 `_v2`、`_v3`,不覆盖旧成品。 --- ## 排错 - **MinerU 解析失败**:核对 `.env` 的 `MINERU_API_TOKEN`(在 https://mineru.net 申请);PDF 应 ≤200MB / ≤200 页;能访问 `mineru.net`。重跑 Step 1 即可(覆盖)。 - **封面没生成(`skipped`)**:通常是既没配可用 `OPENAI_API_KEY`、又没有可复用的论文原图。配上 key 走 AI 生图,或确保 `understanding.important_figures` 有 `suitable_for_cover:true` 且 `image_path` 存在的图以供本地合成回退。 - **配图没生成 / 张数不对**:`post_figures[].image_path` 必须取自 `parsed/figures_index.json` 且文件真实存在(路径错会逐张跳过);`understanding` 没写 `post_figures` 时回退 `important_figures` 按分前 3;全无可用图则 `skipped`。发布只认 `post_images/` 下的 `p<序号>.*` 文件。 - **发布步骤报错**:`未登录` → 按 `references/publish-guide.md` 完成登录(首次注意「新设备验证」);`连不上 mcp` → 看 ① 是否成功起服务(二进制下载/启动失败查 `$XHS_MCP_DIR/mcp.log`)。**登录成功后须重启 mcp 才会加载 cookies**。不发布可跳过 Step 5、手动发产物。publish.py 非零退出(2=未登录、3=连不上)时 `conda run` 会附带打印一行 `ERROR conda.cli.main_run`——那只是退出码传播,不是脚本崩溃。 - **理解/文案不需要 API key**:这两步是你亲自做的,不调用任何 LLM API。 [View on SkillFed](https://skillfed.io/QuZhan51496/paper2anything/paper2xhs) · [View on GitHub](https://github.com/QuZhan51496/paper2anything)