news-extractor
新闻站点内容提取。支持微信公众号、今日头条、网易新闻、搜狐新闻、腾讯新闻。当用户需要提取新闻内容、抓取公众号文章、爬取新闻、或获取新闻JSON/Markdown时激活。
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Install command
npx @skill-hub/cli install nanmicoder-claude-code-skills-news-extractor
Repository
Skill path: plugins/news-extractor/skills/news-extractor
新闻站点内容提取。支持微信公众号、今日头条、网易新闻、搜狐新闻、腾讯新闻。当用户需要提取新闻内容、抓取公众号文章、爬取新闻、或获取新闻JSON/Markdown时激活。
Open repositoryBest for
Primary workflow: Ship Full Stack.
Technical facets: Full Stack.
Target audience: everyone.
License: Unknown.
Original source
Catalog source: SkillHub Club.
Repository owner: NanmiCoder.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install news-extractor into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/NanmiCoder/claude-code-skills before adding news-extractor to shared team environments
- Use news-extractor for development workflows
Works across
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: news-extractor
description: 新闻站点内容提取。支持微信公众号、今日头条、网易新闻、搜狐新闻、腾讯新闻。当用户需要提取新闻内容、抓取公众号文章、爬取新闻、或获取新闻JSON/Markdown时激活。
---
# News Extractor Skill
从主流新闻平台提取文章内容,输出 JSON 和 Markdown 格式。
## 支持平台
| 平台 | ID | URL 示例 |
|------|-----|----------|
| 微信公众号 | wechat | `https://mp.weixin.qq.com/s/xxxxx` |
| 今日头条 | toutiao | `https://www.toutiao.com/article/123456/` |
| 网易新闻 | netease | `https://www.163.com/news/article/ABC123.html` |
| 搜狐新闻 | sohu | `https://www.sohu.com/a/123456_789` |
| 腾讯新闻 | tencent | `https://news.qq.com/rain/a/20251016A07W8J00` |
## 依赖安装
首次使用前需要安装依赖。根据你的环境选择以下任一方式:
### 方式一:使用 uv (推荐)
```bash
cd .claude/skills/news-extractor
# 安装依赖并创建虚拟环境
uv sync
# 运行脚本时 uv 会自动使用虚拟环境
uv run scripts/extract_news.py --list-platforms
```
### 方式二:使用 pip
```bash
cd .claude/skills/news-extractor
# 创建虚拟环境(可选但推荐)
python -m venv .venv
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows
# 安装依赖
pip install -r requirements.txt
# 运行脚本
python scripts/extract_news.py --list-platforms
```
### 依赖列表
| 包名 | 用途 |
|------|------|
| pydantic | 数据模型验证 |
| requests | HTTP 请求 |
| curl_cffi | 浏览器模拟抓取 |
| tenacity | 重试机制 |
| parsel | HTML/XPath 解析 |
| demjson3 | 非标准 JSON 解析 |
## 使用方式
### 基本用法
```bash
# 提取新闻,自动检测平台,输出 JSON + Markdown
uv run .claude/skills/news-extractor/scripts/extract_news.py "URL"
# 指定输出目录
uv run .claude/skills/news-extractor/scripts/extract_news.py "URL" --output ./output
# 仅输出 JSON
uv run .claude/skills/news-extractor/scripts/extract_news.py "URL" --format json
# 仅输出 Markdown
uv run .claude/skills/news-extractor/scripts/extract_news.py "URL" --format markdown
# 列出支持的平台
uv run .claude/skills/news-extractor/scripts/extract_news.py --list-platforms
```
### 输出文件
脚本默认输出两种格式到指定目录(默认 `./output`):
- `{news_id}.json` - 结构化 JSON 数据
- `{news_id}.md` - Markdown 格式文章
## 工作流程
1. **接收 URL** - 用户提供新闻链接
2. **平台检测** - 自动识别平台类型
3. **内容提取** - 调用对应爬虫获取并解析内容
4. **格式转换** - 生成 JSON 和 Markdown
5. **输出文件** - 保存到指定目录
## 输出格式
### JSON 结构
```json
{
"title": "文章标题",
"news_url": "原始链接",
"news_id": "文章ID",
"meta_info": {
"author_name": "作者/来源",
"author_url": "",
"publish_time": "2024-01-01 12:00"
},
"contents": [
{"type": "text", "content": "段落文本", "desc": ""},
{"type": "image", "content": "https://...", "desc": ""},
{"type": "video", "content": "https://...", "desc": ""}
],
"texts": ["段落1", "段落2"],
"images": ["图片URL1", "图片URL2"],
"videos": []
}
```
### Markdown 结构
```markdown
# 文章标题
## 文章信息
**作者**: xxx
**发布时间**: 2024-01-01 12:00
**原文链接**: [链接](URL)
---
## 正文内容
段落内容...

---
## 媒体资源
### 图片 (N)
1. URL1
2. URL2
```
## 使用示例
### 提取微信公众号文章
```bash
uv run .claude/skills/news-extractor/scripts/extract_news.py \
"https://mp.weixin.qq.com/s/ebMzDPu2zMT_mRgYgtL6eQ"
```
输出:
```
[INFO] Platform detected: wechat (微信公众号)
[INFO] Extracting content...
[INFO] Title: 文章标题
[INFO] Author: 公众号名称
[INFO] Text paragraphs: 15
[INFO] Images: 3
[SUCCESS] Saved: ./output/ebMzDPu2zMT_mRgYgtL6eQ.json
[SUCCESS] Saved: ./output/ebMzDPu2zMT_mRgYgtL6eQ.md
```
### 提取今日头条文章
```bash
uv run .claude/skills/news-extractor/scripts/extract_news.py \
"https://www.toutiao.com/article/7434425099895210546/"
```
## 错误处理
| 错误类型 | 说明 | 解决方案 |
|----------|------|----------|
| `无法识别该平台` | URL 不匹配任何支持的平台 | 检查 URL 是否正确 |
| `平台不支持` | 非支持的站点 | 本 Skill 仅支持列出的新闻站点 |
| `提取失败` | 网络错误或页面结构变化 | 重试或检查 URL 有效性 |
## 注意事项
- 仅用于教育和研究目的
- 不要进行大规模爬取
- 尊重目标网站的 robots.txt 和服务条款
- 微信公众号可能需要有效的 Cookie(当前默认配置通常可用)
## 参考
- [平台 URL 模式说明](references/platform-patterns.md)
---
## Referenced Files
> The following files are referenced in this skill and included for context.
### references/platform-patterns.md
```markdown
# 中国新闻平台 URL 模式说明
本文档描述各平台的 URL 格式和特殊注意事项。
## 平台 URL 模式
### 微信公众号 (wechat)
**URL 格式**:
```
https://mp.weixin.qq.com/s/{article_id}
https://mp.weixin.qq.com/s?__biz=xxx&mid=xxx&idx=xxx&sn=xxx
```
**正则模式**:
```regex
https?://mp\.weixin\.qq\.com/s/
```
**特点**:
- 支持传统页面和 SSR 渲染页面(小红书风格)
- 使用 `curl_cffi` 进行 Chrome 模拟
- 可能需要 Cookie(当前默认配置通常可用)
**示例**:
- `https://mp.weixin.qq.com/s/ebMzDPu2zMT_mRgYgtL6eQ`
- `https://mp.weixin.qq.com/s/RUHJpS9w3RhuhEm94z-1Kw` (SSR 渲染)
---
### 今日头条 (toutiao)
**URL 格式**:
```
https://www.toutiao.com/article/{article_id}/
https://www.toutiao.com/article/{article_id}/?log_from=xxx
```
**正则模式**:
```regex
https?://www\.toutiao\.com/article/
```
**特点**:
- 文章 ID 通常为长数字字符串
- URL 末尾可能有或没有斜杠
- 可能包含 `log_from` 追踪参数
**示例**:
- `https://www.toutiao.com/article/7434425099895210546/`
- `https://www.toutiao.com/article/7404384826024935990/?log_from=xxx`
---
### 网易新闻 (netease)
**URL 格式**:
```
https://www.163.com/news/article/{article_id}.html
https://www.163.com/dy/article/{article_id}.html
```
**正则模式**:
```regex
https?://www\.163\.com/(news|dy)/article/
```
**特点**:
- 支持 `news` 和 `dy`(订阅号)两种路径
- 文章 ID 通常为大写字母数字组合
- 内容在 `div.post_body` 中
**示例**:
- `https://www.163.com/news/article/KC12OUHK000189FH.html`
- `https://www.163.com/dy/article/JK7AUN4S0514R9OJ.html`
---
### 搜狐新闻 (sohu)
**URL 格式**:
```
https://www.sohu.com/a/{article_id}_{source_id}
```
**正则模式**:
```regex
https?://www\.sohu\.com/a/
```
**特点**:
- URL 包含文章 ID 和来源 ID(下划线分隔)
- 图片 URL 可能被加密,需要从 JavaScript 提取真实 URL
- 内容在 `article#mp-editor` 中
**示例**:
- `https://www.sohu.com/a/945014338_160447`
---
### 腾讯新闻 (tencent)
**URL 格式**:
```
https://news.qq.com/rain/a/{article_id}
```
**正则模式**:
```regex
https?://news\.qq\.com/rain/a/
```
**特点**:
- 文章 ID 包含日期和字母数字组合
- 元信息存储在 `window.DATA` JavaScript 变量中
- 内容在 `div.rich_media_content` 中
**示例**:
- `https://news.qq.com/rain/a/20251016A07W8J00`
---
## 平台检测逻辑
检测器使用正则表达式按顺序匹配:
```python
PLATFORM_PATTERNS = {
"toutiao": r"https?://www\.toutiao\.com/article/",
"wechat": r"https?://mp\.weixin\.qq\.com/s/",
"netease": r"https?://www\.163\.com/(news|dy)/article/",
"sohu": r"https?://www\.sohu\.com/a/",
"tencent": r"https?://news\.qq\.com/rain/a/",
}
```
## 常见问题
### Q: 为什么提取失败?
可能原因:
1. **Cookie 过期** - 尝试更新 Cookie 配置
2. **页面结构变化** - 平台可能更新了页面模板
3. **反爬策略** - 请求频率过高触发限制
4. **网络问题** - 检查网络连接
### Q: 如何获取新 Cookie?
1. 打开浏览器访问目标平台
2. 打开开发者工具 (F12)
3. 访问一篇文章
4. 在 Network 面板找到主请求
5. 复制 Cookie 头
### Q: 图片无法显示?
某些平台(如微信)的图片有防盗链:
- 微信图片需要特定 Referer
- 搜狐图片可能是加密的 Base64
- 建议在需要时使用 `embed_images=True` 将图片嵌入 Markdown
### Q: 支持批量提取吗?
当前版本仅支持单个 URL 提取。如需批量提取,可以:
1. 使用 shell 循环
2. 或直接调用 `news_extractor_core.services.extractor.ExtractorService`
```
### scripts/extract_news.py
```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
中国新闻提取脚本
使用方式:
uv run extract_news.py "URL" [--output DIR] [--format json|markdown|both]
支持平台:
- 微信公众号 (wechat)
- 今日头条 (toutiao)
- 网易新闻 (netease)
- 搜狐新闻 (sohu)
- 腾讯新闻 (tencent)
"""
import argparse
import json
import sys
from pathlib import Path
from typing import Optional
# 添加当前目录到路径
SCRIPT_DIR = Path(__file__).resolve().parent
sys.path.insert(0, str(SCRIPT_DIR))
from models import NewsItem
from detector import detect_platform, get_platform_name, PLATFORM_NAMES
from formatter import to_markdown
from crawlers.wechat import WeChatNewsCrawler
from crawlers.toutiao import ToutiaoNewsCrawler
from crawlers.netease import NeteaseNewsCrawler
from crawlers.sohu import SohuNewsCrawler
from crawlers.tencent import TencentNewsCrawler
# 爬虫映射
CRAWLERS = {
"wechat": WeChatNewsCrawler,
"toutiao": ToutiaoNewsCrawler,
"netease": NeteaseNewsCrawler,
"sohu": SohuNewsCrawler,
"tencent": TencentNewsCrawler,
}
def log_info(msg: str) -> None:
"""输出信息日志"""
print(f"[INFO] {msg}")
def log_success(msg: str) -> None:
"""输出成功日志"""
print(f"[SUCCESS] {msg}")
def log_error(msg: str) -> None:
"""输出错误日志"""
print(f"[ERROR] {msg}", file=sys.stderr)
def extract_news(
url: str,
output_dir: str = "./output",
output_format: str = "both",
platform: Optional[str] = None,
) -> int:
"""
提取新闻内容
Args:
url: 新闻 URL
output_dir: 输出目录
output_format: 输出格式 (json, markdown, both)
platform: 指定平台(可选,默认自动检测)
Returns:
0 表示成功,1 表示失败
"""
# 1. 平台检测
detected_platform = platform or detect_platform(url)
if not detected_platform:
log_error("无法识别该平台,请检查 URL 是否正确")
log_info("支持的中国新闻平台:")
for pid, pname in PLATFORM_NAMES.items():
log_info(f" - {pname} ({pid})")
return 1
# 检查是否为支持的平台
if detected_platform not in CRAWLERS:
log_error(f"平台 '{detected_platform}' 不支持")
log_info("支持的中国新闻平台:")
for pid, pname in PLATFORM_NAMES.items():
log_info(f" - {pname} ({pid})")
return 1
platform_name = get_platform_name(detected_platform)
log_info(f"Platform detected: {detected_platform} ({platform_name})")
# 2. 提取内容
log_info("Extracting content...")
try:
crawler_class = CRAWLERS[detected_platform]
crawler = crawler_class(url, save_path=output_dir)
news_item = crawler.run(persist=False) # 不使用爬虫自带的保存
except ValueError as e:
log_error(f"提取失败: {e}")
return 1
except Exception as e:
log_error(f"未知错误: {e}")
return 1
# 3. 显示提取结果摘要
log_info(f"Title: {news_item.title}")
if news_item.meta_info.author_name:
log_info(f"Author: {news_item.meta_info.author_name}")
if news_item.meta_info.publish_time:
log_info(f"Publish time: {news_item.meta_info.publish_time}")
log_info(f"Text paragraphs: {len(news_item.texts)}")
log_info(f"Images: {len(news_item.images)}")
if news_item.videos:
log_info(f"Videos: {len(news_item.videos)}")
# 4. 创建输出目录
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
# 5. 生成输出文件
news_id = news_item.news_id or "untitled"
# 清理文件名中的非法字符
safe_id = "".join(c if c.isalnum() or c in "-_" else "_" for c in news_id)
# JSON 输出
if output_format in ("json", "both"):
json_file = output_path / f"{safe_id}.json"
with open(json_file, "w", encoding="utf-8") as f:
json.dump(news_item.to_dict(), f, ensure_ascii=False, indent=2)
log_success(f"Saved: {json_file}")
# Markdown 输出
if output_format in ("markdown", "both"):
md_file = output_path / f"{safe_id}.md"
markdown_content = to_markdown(news_item, platform=detected_platform)
with open(md_file, "w", encoding="utf-8") as f:
f.write(markdown_content)
log_success(f"Saved: {md_file}")
return 0
def list_platforms() -> None:
"""列出支持的平台"""
print("支持的中国新闻平台:")
print()
for pid, pname in PLATFORM_NAMES.items():
print(f" {pname} ({pid})")
print()
print("URL 格式示例:")
print(" - 微信公众号: https://mp.weixin.qq.com/s/xxxxx")
print(" - 今日头条: https://www.toutiao.com/article/123456/")
print(" - 网易新闻: https://www.163.com/news/article/ABC123.html")
print(" - 搜狐新闻: https://www.sohu.com/a/123456_789")
print(" - 腾讯新闻: https://news.qq.com/rain/a/20251016A07W8J00")
def main():
"""主入口"""
parser = argparse.ArgumentParser(
description="中国新闻内容提取工具",
epilog="支持平台: 微信公众号、今日头条、网易新闻、搜狐新闻、腾讯新闻",
)
parser.add_argument(
"url",
nargs="?",
help="新闻 URL",
)
parser.add_argument(
"--output", "-o",
default="./output",
help="输出目录 (默认: ./output)",
)
parser.add_argument(
"--format", "-f",
choices=["json", "markdown", "both"],
default="both",
help="输出格式 (默认: both)",
)
parser.add_argument(
"--platform", "-p",
choices=list(PLATFORM_NAMES.keys()),
help="指定平台 (可选,默认自动检测)",
)
parser.add_argument(
"--list-platforms",
action="store_true",
help="列出支持的平台",
)
args = parser.parse_args()
# 列出平台
if args.list_platforms:
list_platforms()
return 0
# 检查 URL 是否提供
if not args.url:
parser.print_help()
return 1
# 执行提取
return extract_news(
url=args.url,
output_dir=args.output,
output_format=args.format,
platform=args.platform,
)
if __name__ == "__main__":
sys.exit(main())
```