first commit

This commit is contained in:
Hermes Agent
2026-05-10 13:52:46 +08:00
commit ccc63d1e70
4583 changed files with 584341 additions and 0 deletions

View File

@@ -0,0 +1,304 @@
# WeChat Article Extractor
[![Node.js](https://img.shields.io/badge/Node.js-14+-green.svg)](https://nodejs.org/)
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
一个 Claude Code Skill用于提取微信公众号文章的元数据和内容。支持多种文章类型包括图文、视频、图片集、语音和转载文章。当用户需要提供微信公众号文章链接mp.weixin.qq.comClaude 会自动触发此 Skill 来提取文章信息。
## 功能特性
- 解析微信公众号文章 URL (`mp.weixin.qq.com`)
- 提取文章元数据:标题、作者、摘要、发布时间
- 获取公众号信息:名称、头像、微信号、功能介绍
- 提取文章内容HTML 格式)
- 获取封面图片 URL
- 支持多种文章类型:图文、视频、图片集、语音、纯文字、转载
- 处理各种异常情况:内容删除、链接过期、访问限制、账号迁移等
- 支持搜狗微信搜索结果的解析 (`weixin.sogou.com`)
- 可选提取文章标签和内嵌链接
## 安装
这是一个 Claude Code Skill可以通过以下方式安装
### 通过 Claude Code 安装(推荐)
在 Claude Code 中运行:
```
/skill install wechat-article-extractor
```
或指定目录安装:
```
/skill install /path/to/wechat-article-extractor-skill
```
### 手动克隆安装
```bash
git clone https://github.com/yourusername/wechat-article-extractor-skill.git
cd wechat-article-extractor-skill
npm install
```
然后在 Claude Code 中将该目录作为 Skill 加载。
## 使用方法
### 基本用法 - 从 URL 提取
```javascript
const { extract } = require('./scripts/extract.js');
async function main() {
const url = 'https://mp.weixin.qq.com/s?__biz=...&mid=...&idx=...&sn=...';
const result = await extract(url);
if (result.done) {
console.log('文章标题:', result.data.msg_title);
console.log('公众号:', result.data.account_name);
console.log('发布时间:', result.data.msg_publish_time_str);
} else {
console.error('提取失败:', result.msg);
}
}
main();
```
### 从 HTML 内容提取
如果你已经获取了页面 HTML可以直接传入
```javascript
const { extract } = require('./scripts/extract.js');
async function main() {
const html = await fetch(url).then(r => r.text());
const result = await extract(html, { url: sourceUrl });
console.log(result);
}
main();
```
### 高级选项
```javascript
const result = await extract(url, {
shouldReturnContent: true, // 返回 HTML 内容默认true
shouldReturnRawMeta: false, // 返回原始元数据默认false
shouldFollowTransferLink: true, // 自动跟随迁移后的公众号链接默认true
shouldExtractMpLinks: false, // 提取内嵌的微信公众号链接默认false
shouldExtractTags: false, // 提取文章标签默认false
shouldExtractRepostMeta: false // 提取转载来源信息默认false
});
```
## 响应格式
### 成功响应
```javascript
{
done: true,
code: 0,
data: {
// 公众号信息
account_name: "公众号名称",
account_alias: "微信号",
account_avatar: "头像URL",
account_description: "功能介绍",
account_id: "原始ID",
account_biz: "biz参数",
account_biz_number: 1234567890,
account_qr_code: "二维码URL",
// 文章信息
msg_title: "文章标题",
msg_desc: "文章摘要",
msg_content: "HTML内容",
msg_cover: "封面图URL",
msg_author: "作者",
msg_type: "post", // post|video|image|voice|text|repost
msg_has_copyright: true,
msg_publish_time: Date,
msg_publish_time_str: "2024/01/15 10:30:00",
// 链接参数
msg_link: "文章链接",
msg_source_url: "阅读原文链接",
msg_sn: "sn参数",
msg_mid: 1234567890,
msg_idx: 1
}
}
```
### 错误响应
```javascript
{
done: false,
code: 1001,
msg: "无法获取文章信息"
}
```
## 错误代码表
| 代码 | 错误信息 | 说明 |
|------|----------|------|
| 1000 | 文章获取失败 | 一般性失败 |
| 1001 | 无法获取文章信息 | 缺少标题或发布时间 |
| 1002 | 请求失败 | HTTP 请求失败 |
| 1003 | 响应为空 | 空响应 |
| 1004 | 访问过于频繁 | 被限流 |
| 1005 | 脚本解析失败 | 页面脚本解析错误 |
| 1006 | 公众号已迁移 | 账号已迁移,包含新链接 |
| 2001 | 请提供文章内容或链接 | 缺少输入参数 |
| 2002 | 链接已过期 | 链接已失效 |
| 2003 | 内容涉嫌侵权 | 内容因侵权被移除 |
| 2004 | 无法获取迁移后的链接 | 迁移链接获取失败 |
| 2005 | 内容已被发布者删除 | 作者已删除内容 |
| 2006 | 内容因违规无法查看 | 内容被平台屏蔽 |
| 2007 | 内容发送失败 | 发送失败 |
| 2008 | 系统出错 | 系统错误 |
| 2009 | 不支持的链接 | URL 格式不支持 |
| 2010 | 内容获取失败 | 内容获取失败 |
| 2011 | 涉嫌过度营销 | 营销/垃圾内容 |
| 2012 | 账号已被屏蔽 | 账号被封禁 |
| 2013 | 账号已自主注销 | 账号已注销 |
| 2014 | 内容被投诉 | 内容被举报 |
| 2015 | 账号处于迁移流程中 | 账号正在迁移 |
| 2016 | 冒名侵权 | 冒充侵权 |
## 支持的文章类型
| 类型 | 说明 | msg_type |
|------|------|----------|
| 图文 | 普通图文文章 | `post` |
| 视频 | 视频内容 | `video` |
| 图片集 | 多张图片展示 | `image` |
| 语音 | 音频内容 | `voice` |
| 纯文字 | 无标题文字内容 | `text` |
| 转载 | 转载他人文章 | `repost` |
## 项目结构
```
wechat-article-extractor-skill/
├── scripts/
│ ├── extract.js # 核心提取逻辑
│ └── errors.js # 错误代码定义
├── SKILL.md # Skill 定义文件Claude Skill 格式,包含触发条件和描述)
├── package.json # 项目配置
└── README.md # 本文件
```
## 依赖项
- `cheerio` - 服务端 HTML 解析
- `dayjs` - 日期格式化
- `request-promise` - HTTP 请求
- `qs` - 查询字符串解析
- `lodash.unescape` - HTML 实体解码
## 注意事项
1. **频率限制**: 频繁请求可能会导致 IP 被暂时封禁,建议添加适当的延迟
2. **页面结构**: 微信页面结构可能会变化,如遇问题请检查是否为最新版本
3. **Cookie**: 某些文章可能需要登录才能访问完整内容
4. **反爬措施**: 请遵守微信的使用条款,合理使用本工具
## 示例应用
### 批量提取文章
```javascript
const { extract } = require('./scripts/extract.js');
async function batchExtract(urls) {
const results = [];
for (const url of urls) {
try {
const result = await extract(url);
if (result.done) {
results.push({
title: result.data.msg_title,
author: result.data.account_name,
publishTime: result.data.msg_publish_time_str
});
}
// 添加延迟避免被限流
await new Promise(r => setTimeout(r, 1000));
} catch (err) {
console.error(`提取失败: ${url}`, err.message);
}
}
return results;
}
const urls = [
'https://mp.weixin.qq.com/s?__biz=...',
'https://mp.weixin.qq.com/s?__biz=...'
];
batchExtract(urls).then(console.log);
```
### 保存为 Markdown
```javascript
const { extract } = require('./scripts/extract.js');
const fs = require('fs');
async function saveAsMarkdown(url, filename) {
const result = await extract(url);
if (!result.done) {
console.error('提取失败:', result.msg);
return;
}
const { data } = result;
const markdown = `
# ${data.msg_title}
> 作者: ${data.msg_author || data.account_name}
> 公众号: ${data.account_name}
> 发布时间: ${data.msg_publish_time_str}
${data.msg_content}
---
原文链接: [${data.msg_link}](${data.msg_link})
`;
fs.writeFileSync(filename, markdown);
console.log(`已保存: ${filename}`);
}
saveAsMarkdown('https://mp.weixin.qq.com/s?__biz=...', 'article.md');
```
## 许可证
[MIT](LICENSE)
## 贡献
欢迎提交 Issue 和 Pull Request
## 更新日志
### v1.0.0
- 初始版本发布
- 支持基本的文章信息提取
- 支持多种文章类型
- 完善的错误处理机制