为政策雷达 skill 添加11个政府网站的 Python 抓取工具
覆盖全部11个数据源的可复用 scraper 模块 tools/scrapers.py: - gov.cn: 国务院政策文件库(HTML 解析) - xinhuanet (news.cn): 新华社受权发布(HTML 解析) - scio (pbc镜像): 国新办新闻发布会文字实录 - pbc: 央行货币政策/公告 - mof: 财政部政策 - ndrc: 发改委产业政策 - csrc: 证监会公告(HTML 解析) - mofcom: 商务部政策(JSON API) - people: 人民日报社论(HTML 解析) - cctv: 央视新闻联播(JSONP API) - ce: 经济日报政策解读 更新 SKILL.md 引用新工具,统一入口 scrape_list()/scrape_article()。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -0,0 +1,371 @@
|
||||
---
|
||||
name: policy-radar
|
||||
description: 政策雷达 — 从中国政府公开信息源抓取最新政策原文,按「李铁四步法」进行结构化深度分析,输出投资方向的判断报告。输入关键词或时间范围,自动搜索→抓取→解读→输出。
|
||||
---
|
||||
|
||||
# 政策雷达 (Policy Radar)
|
||||
|
||||
> 可执行的政策解读智能体:从政策原文抓取到投资方向判断的完整工作流。
|
||||
> 基于李铁(铁哥)在中国资本市场的政策解读方法论。
|
||||
|
||||
---
|
||||
|
||||
## 1. 角色与目标
|
||||
|
||||
**角色:** 你是一个政策分析师,专为中国A股市场的投资者提供政策解读服务。你不会凭空猜测——所有判断都基于政策原文。
|
||||
|
||||
**目标产物:** 一份 `policy-analysis.md`,包含:
|
||||
1. 本期抓取到的所有相关政策清单(附原文链接/引文)
|
||||
2. 每条政策的四步法解读
|
||||
3. 政策连续性验证(对比上一期分析)
|
||||
4. 投资方向判断(大方向/中方向/小方向)
|
||||
|
||||
---
|
||||
|
||||
## 2. 可执行 SOP(六步)
|
||||
|
||||
### 阶段 A: 搜集政策原文
|
||||
|
||||
**Step 1 — 确认搜索范围。**
|
||||
|
||||
- 用户输入:关键词(如「科技金融」「消费」「房地产」)或时间范围(如「最近一周」「本月」)
|
||||
- 默认:最近7天所有重要政策
|
||||
|
||||
**Step 2 — 搜索并抓取政策原文。**
|
||||
|
||||
按以下顺序依次搜索和抓取:
|
||||
|
||||
```
|
||||
优先级 1: 中央政府门户
|
||||
├── 中国政府网 (www.gov.cn) → 国务院政策文件库
|
||||
├── 国新办官网 (www.scio.gov.cn) → 新闻发布会文字实录
|
||||
└── 新华社 (www.xinhuanet.com) → 受权发布/时政
|
||||
|
||||
优先级 2: 部委官网
|
||||
├── 中国人民银行 (www.pbc.gov.cn) → 货币政策/公告
|
||||
├── 财政部 (www.mof.gov.cn) → 财政政策/预算报告
|
||||
├── 证监会 (www.csrc.gov.cn) → 主席讲话/政策公告
|
||||
├── 发改委 (www.ndrc.gov.cn) → 产业政策/规划
|
||||
└── 商务部 (www.mofcom.gov.cn) → 外贸/消费政策
|
||||
|
||||
优先级 3: 权威媒体转载
|
||||
├── 人民日报 (www.people.com.cn) → 社论/政策解读
|
||||
├── 央视新闻 (news.cctv.com) → 新闻联播文字版
|
||||
└── 经济日报 (www.ce.cn) → 部委政策解读
|
||||
```
|
||||
|
||||
**搜索方法:** 使用 WebSearch 工具,搜索格式为:
|
||||
- `site:gov.cn {关键词} {年份}`
|
||||
- `国新办 新闻发布会 {年份}年{月份}`
|
||||
- `中共中央政治局会议 {年份}年{月份}`
|
||||
- `site:scio.gov.cn 新闻发布会`
|
||||
|
||||
**抓取方法:** 对每个搜索结果使用 WebFetch 工具,提取:
|
||||
- 完整标题
|
||||
- 发布时间
|
||||
- 发布机构
|
||||
- 核心内容段落(不是摘要,是原文段落)
|
||||
|
||||
**最少抓取量:** 每次分析至少抓取 3 条原始政策文本,至多 10 条。如无新政策,显式报告「本期无重大新政策」。
|
||||
|
||||
**Step 3 — 排除「非政策」。**
|
||||
|
||||
以下不纳入分析:
|
||||
- 纯新闻报道(无政策内容)
|
||||
- 地方性政策(除非是试点/范本级别)
|
||||
- 行业协会倡议(无政府背书)
|
||||
- 评论文章/专家观点(非政策本身)
|
||||
|
||||
---
|
||||
|
||||
### 阶段 B: 四步法解读
|
||||
|
||||
**Step 4 — 对每条政策依次执行四步法。**
|
||||
|
||||
#### 4.1 读原文:定位核心段落
|
||||
|
||||
从抓取到的原文中,找出以下关键信息:
|
||||
- **政策目标**:这份文件要解决什么问题?
|
||||
- **具体措施**:提到了哪些实际手段?(财政补贴/税收优惠/牌照放开/准入限制/金融支持……)
|
||||
- **措辞强度**:用了什么级别的动词?(「支持」<「推动」<「加快」<「举国」<「志在必得」)
|
||||
- **量化指标**:有没有具体数字?
|
||||
|
||||
#### 4.2 找新增:与上一期对比
|
||||
|
||||
将本期政策与上一期分析(如果存在)逐条对比:
|
||||
|
||||
| 对比维度 | 判断标准 |
|
||||
|----------|----------|
|
||||
| **新增表述** | 以前没出现过的新词/新概念 → 标记为「新方向」 |
|
||||
| **排序变化** | 同一议题在不同文件中位置前移/后移 |
|
||||
| **措辞升级** | 「支持」→「推动」→「举国体制」 |
|
||||
| **新增措施** | 以前没有的具体手段首次出现 |
|
||||
| **删除内容** | 以前强调的本期不再提及 |
|
||||
|
||||
**基线建立规则(硬步骤,不可跳过):**
|
||||
|
||||
- **非首次运行**: 将本期政策与上一期 `policy-analysis-{上期日期}.md` 的结论逐条对比,标注每条政策的「新增表述/措辞变化/排序变化/新增措施/删除内容」。
|
||||
- **首次运行**: 必须执行「基线扫描」子步骤——搜索过去 3 个月的相关政策(至少覆盖本次关键词领域),建立一份简短的基线摘要(每条政策的核心方向+关键措辞),作为 4.2 的对比锚点。基线摘要写入报告的「基线对比」字段,不得省略。
|
||||
- **后续运行输入**: 将上一期 `policy-analysis-{日期}.md` 作为上下文输入,使 4.2 的增量判断可验证,而非依赖 agent 的历史知识。
|
||||
|
||||
#### 4.3 分类:区分货币政策与财政政策
|
||||
|
||||
| 政策类型 | 工具 | 对投资的意义 |
|
||||
|----------|------|-------------|
|
||||
| **货币政策** | 降准、降息、MLF、再贷款 | 全面流动性利好 |
|
||||
| **财政政策** | 特别国债、政府投资基金、直接补贴、减税降费 | 结构性机会,钱流向政府指定领域 |
|
||||
| **产业政策** | 行业规划、牌照管理、准入标准 | 直接利好/利空特定赛道 |
|
||||
| **分配政策** | 社保、医疗、教育、住房 | 影响消费预期和居民杠杆 |
|
||||
|
||||
#### 4.4 跟踪连续性:串联成链
|
||||
|
||||
将所有政策按时间顺序排列,标注每条政策的「方向指向」,检查是否形成连贯链条:
|
||||
|
||||
```
|
||||
[会议A] 说要搞X → [会议B] 推出X的具体措施 → [会议C] 加码X的财政支持 → 连续性确认
|
||||
```
|
||||
如果链条断裂(如会议B突然不提X),标记为「方向可能转变」。
|
||||
|
||||
**跨赛道分支标注**: 当多条政策分属不同赛道但共享同一宏观主题(如绿色转型、扩大内需)时,用分支箭头标注关联关系,避免孤立分析。格式见第 4 节模板中的链条图示例。
|
||||
|
||||
---
|
||||
|
||||
### 阶段 C: 输出分析
|
||||
|
||||
**Step 5 — 生成结构化分析报告。**
|
||||
|
||||
使用以下模板(第4节)生成 `policy-analysis.md`。
|
||||
|
||||
**Step 6 — 写入文件并汇报。**
|
||||
|
||||
将报告写入工作目录,并向用户汇报核心结论(不超过300字)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 五层政策优先级(用于筛选和分析排序)
|
||||
|
||||
| 层级 | 来源 | 权重 | 更新频率 |
|
||||
|------|------|------|----------|
|
||||
| **P0** | 中央全会报告/政治局会议决议 | ★★★★★ | 每5年/每年数次 |
|
||||
| **P1** | 国新办新闻发布会 | ★★★★ | 每周可能多次 |
|
||||
| **P2** | 政府工作报告/五年规划 | ★★★★ | 每年一次 |
|
||||
| **P3** | 部委级政策/监管表态 | ★★★ | 每月可能多次 |
|
||||
| **P4** | 区域政策/试点方案 | ★★ | 不定期 |
|
||||
|
||||
**操作规则:**
|
||||
- P0 和 P1 政策必须全文解读
|
||||
- P2 只看新增措辞和变化
|
||||
- P3 精选与投资方向相关的
|
||||
- P4 仅当作为全国政策试点范本时纳入
|
||||
|
||||
---
|
||||
|
||||
## 4. 输出模板
|
||||
|
||||
```markdown
|
||||
# 政策雷达分析报告 — {日期}
|
||||
|
||||
> 分析范围:{关键词/时间范围}
|
||||
> 政策抓取数量:{数量} 条
|
||||
> 基线对比:{本期/上一期日期}
|
||||
|
||||
## 1. 政策清单
|
||||
|
||||
| # | 政策名称 | 发布机构 | 日期 | 优先级 | 原文链接 |
|
||||
|---|----------|----------|------|--------|----------|
|
||||
| 1 | ... | ... | ... | P0 | ... |
|
||||
| 2 | ... | ... | ... | P1 | ... |
|
||||
|
||||
## 2. 四步法逐条解读
|
||||
|
||||
### 政策 1: {标题}
|
||||
|
||||
**原文摘要:** {200字以内的原文核心段落}
|
||||
|
||||
**4.1 读原文:**
|
||||
- 政策目标: ...
|
||||
- 具体措施: ...
|
||||
- 措辞强度: {动词+级别}
|
||||
- 量化指标: ...
|
||||
|
||||
**4.2 找新增(vs 上期):**
|
||||
- 新增表述: ...(如首次出现则标注「新方向」)
|
||||
- 措辞变化: ...
|
||||
- 是否首次提出: 是/否
|
||||
|
||||
**4.3 政策类型:** 货币/财政/产业/分配
|
||||
|
||||
**4.4 连续性验证:**
|
||||
- 与前序政策的关系: {延续/加码/转向}
|
||||
- 方向一致性: {一致/存疑/转向}
|
||||
|
||||
## 3. 连续性总览
|
||||
|
||||
```
|
||||
{时间线图表,支持分支标注——跨赛道政策关系用分支箭头表示}
|
||||
```
|
||||
|
||||
格式要求:
|
||||
- **主线链条**: 同一议题的政策按时间顺序串联(延续 → 加码 → 转向)
|
||||
- **分支关联**: 跨赛道政策用分支箭头标注(如环保 ←→ 新能源同属绿色转型),格式:`↗ [赛道名] 政策X: 关联描述`
|
||||
- **每条节点**: 标注政策编号 + 方向措辞 + 赛道标签
|
||||
|
||||
示例:
|
||||
```
|
||||
[政策7: 适度宽松+供强需弱] (货币)
|
||||
↓ 延续
|
||||
[政策6: 宽松+框架改革] (货币)
|
||||
↓ 一致
|
||||
[政策5: 零碳园区100个] (产业·新能源)
|
||||
│ ↗ [环保] 政策1: 同属绿色转型链条
|
||||
↓ 一致
|
||||
[政策2: 消费60万亿] (财政·消费)
|
||||
│ ↗ [医疗] 政策3: 同日批复,同属15FYP批量落地
|
||||
↓ 一致
|
||||
[政策1: 县乡水体治理] (产业·环保)
|
||||
```
|
||||
|
||||
**方向是否恒定:** 是/否
|
||||
**转变信号(如有):** ...
|
||||
**跨赛道关联(如有):** 政策X ←→ 政策Y 同属 {赛道名} 链条
|
||||
|
||||
## 4. 投资方向判断
|
||||
|
||||
### 大方向(市场整体)
|
||||
- 判断: ...
|
||||
- 依据: {政策编号} 中的 ...
|
||||
|
||||
### 中方向(赛道选择)
|
||||
- 看好的赛道: ...
|
||||
- 依据: {政策编号} 中的 ...
|
||||
- 看空的赛道: ...
|
||||
- 依据: {政策编号} 中的 ...
|
||||
|
||||
### 小方向(赛道内部)
|
||||
- 具体机会: ...
|
||||
- 风险提示: ...
|
||||
|
||||
## 5. 关键词
|
||||
`关键词1` `关键词2` `关键词3` ...
|
||||
|
||||
## 6. 发布前自检(内嵌,发布前必须逐项打勾)
|
||||
|
||||
- [ ] **原文可追溯:** 每条政策都有原文链接或原文引文(部分/降级已标注)
|
||||
- [ ] **四步法齐全:** 每条政策都经过 4.1→4.2→4.3→4.4 四步,缺失项已标注「原文不可得」
|
||||
- [ ] **基线对比完成:** 非首次运行时对比了上一期报告;首次运行时执行了 3 个月基线扫描
|
||||
- [ ] **方向判断有依据:** 每个投资判断(含看空赛道)都指向具体政策编号
|
||||
- [ ] **无臆测:** 所有分析基于原文,推测部分标注「(推测,非原文)」
|
||||
- [ ] **优先级标注:** 每条政策标注了 P0-P4 优先级
|
||||
- [ ] **降级标注:** 原文获取不完整的政策已添加 ⚠️ 降级标注
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 抓取工具与方法
|
||||
|
||||
### 5.1 可复用抓取工具(推荐)
|
||||
|
||||
skill 目录下提供了预构建的 Python 抓取模块 `tools/scrapers.py`,覆盖全部 11 个数据源。**优先使用这些工具,而非临时编写 curl 脚本。**
|
||||
|
||||
```python
|
||||
import sys
|
||||
sys.path.insert(0, '.claude/skills/policy-radar')
|
||||
from tools.scrapers import scrape_list, scrape_article
|
||||
|
||||
# 获取某站点的最新列表
|
||||
items = scrape_list("gov.cn") # 返回 [{title, date, url}, ...]
|
||||
items = scrape_list("pbc") # 央行货币政策/公告
|
||||
items = scrape_list("people") # 人民日报社论
|
||||
|
||||
# 抓取某篇文章正文
|
||||
article = scrape_article("gov.cn", url) # 返回 [{text}, ...]
|
||||
```
|
||||
|
||||
**支持的站点名称:** `gov.cn`, `xinhuanet`, `pbc`, `mof`, `ndrc`, `csrc`, `mofcom`, `people`, `cctv`, `ce`, `scio`
|
||||
|
||||
### 5.2 工具选择
|
||||
|
||||
| 工具 | 适用场景 | 缺点 |
|
||||
|------|----------|------|
|
||||
| **tools/scrapers.py(推荐)** | 直接调用预置抓取器,覆盖11个源 | 网站结构变更时需更新正则 |
|
||||
| WebSearch | 通用搜索,找最新政策链接 | 依赖配额,可能 403 |
|
||||
| WebFetch | 获取单个页面全文 | 依赖配额,部分站点证书问题 |
|
||||
| curl + python3 | 直接 HTTP 请求 + HTML 解析 | 需处理编码和动态页面 |
|
||||
|
||||
**当预置工具不可用时,使用 curl + python3 作为降级方案。**
|
||||
|
||||
### 5.3 原文获取质量与降级标注
|
||||
|
||||
当抓取工具无法获取完整原文时,**必须显式降级标注**,不得让读者误以为分析覆盖了全文:
|
||||
|
||||
| 获取程度 | 判定条件 | 标注格式 |
|
||||
|----------|----------|----------|
|
||||
| **完整原文** | 获取到政策正文 ≥ 5 个核心段落 | 无需额外标注 |
|
||||
| **部分原文** | 仅获取到摘要、解读页、或 < 5 个段落 | `> ⚠️ 本文基于 gov.cn 政策解读页整理,全文见原文链接` |
|
||||
| **仅标题/元数据** | 链接不可达或返回 404/空白 | `> ⚠️ 原文不可得(链接失效/需登录),本条基于二手分析,结论可信度降低` |
|
||||
|
||||
**规则:**
|
||||
- 降级标注写在每条政策的「原文摘要」字段开头。
|
||||
- 仅标题/元数据时,该政策的「4.1 读原文」中缺失项标注「原文不可得」,**不得臆测填充**。
|
||||
- 原文获取程度直接影响该政策在投资方向判断中的权重——仅标题的政策不应用于看空/看涨的核心依据。
|
||||
|
||||
### 5.4 抓取注意事项
|
||||
|
||||
1. **编码**: gov.cn 和 pbc.gov.cn 均使用 UTF-8;curl 直接读取二进制再 decode 即可。
|
||||
2. **超时**: 建议 `--max-time 15`,避免慢站点阻塞。
|
||||
3. **反爬**: gov.cn 无严格反爬,但连续抓取间隔 1-2 秒为佳。
|
||||
4. **动态内容**: gov.cn 政策列表页是服务端渲染,直接 curl 可获取。部委子页面(如 pbc.gov.cn 发文列表)同上。
|
||||
5. **404 风险**: 政策 URL 可通过列表页 `/zhengce/` 的 `<a href>` 确认,不要猜测 content ID 序列。
|
||||
6. **政策解读页**: gov.cn 政策解读(`/zhengce/jiedu/`)的链接格式与政策原文(`/zhengce/content/`)不同,注意区分。
|
||||
|
||||
---
|
||||
|
||||
## 6. 数据源 URL 速查
|
||||
|
||||
| 来源 | URL | 内容 | 工具名 |
|
||||
|------|-----|------|--------|
|
||||
| 中国政府网 | https://www.gov.cn/zhengce/ | 国务院政策文件库 | `gov.cn` |
|
||||
| 新华社 | https://www.news.cn/ | 受权发布/时政 | `xinhuanet` |
|
||||
| 国新办 | https://www.scio.gov.cn/xwfbh/ | 新闻发布会文字实录 | `scio` (镜像: pbc.gov.cn) |
|
||||
| 央行 | https://www.pbc.gov.cn/goutongjiaoliu/113456/ | 货币政策/公告 | `pbc` |
|
||||
| 财政部 | https://www.mof.gov.cn/zhengwuxinxi/ | 财政政策 | `mof` |
|
||||
| 发改委 | https://www.ndrc.gov.cn/xxgk/ | 产业政策/规划 | `ndrc` |
|
||||
| 证监会 | https://www.csrc.gov.cn/csrc/c100028/ | 证监会公告 | `csrc` |
|
||||
| 商务部 | https://www.mofcom.gov.cn/ | 外贸/消费政策 | `mofcom` |
|
||||
| 人民日报 | http://opinion.people.com.cn/ | 社论/评论 | `people` |
|
||||
| 央视新闻 | https://news.cctv.com/ | 新闻联播文字版 | `cctv` |
|
||||
| 经济日报 | http://www.ce.cn/ | 部委政策解读 | `ce` |
|
||||
|
||||
**注意事项:**
|
||||
- 国新办 (scio.gov.cn) 有 JS 反爬挑战,工具使用央行镜像站获取国新办发布会实录
|
||||
- 新华社内容已迁移至 www.news.cn(旧域名 xinhuanet.com 仅有历史内容)
|
||||
- 人民日报社论版使用 opinion.people.com.cn 子域名
|
||||
|
||||
---
|
||||
|
||||
## 7. 发布前自检说明
|
||||
|
||||
> 自检清单已内嵌到报告模板第 6 节。发布前必须逐项打勾,全部通过方可提交。本节保留各检查项的详细说明供参考。
|
||||
|
||||
1. **原文可追溯** — 每条政策都有原文链接或原文引文。原文获取不完整时须有 ⚠️ 降级标注。
|
||||
2. **四步法齐全** — 每条政策都经过 4.1→4.2→4.3→4.4 四步。缺失项不得臆测填充,应标注「原文不可得」。
|
||||
3. **基线对比** — 非首次运行对比上一期 `policy-analysis-{日期}.md`;首次运行执行 3 个月基线扫描并建立基线摘要。
|
||||
4. **方向判断有依据** — 每个投资判断(含看空赛道)指向具体政策编号,格式为 `{政策编号} 中的 ...`。
|
||||
5. **无臆测** — 所有分析基于原文。推测部分必须标注「(推测,非原文)」。
|
||||
6. **优先级标注** — 每条政策在清单中标注了 P0-P4 优先级。
|
||||
|
||||
---
|
||||
|
||||
## 8. 反模式(出现即重写)
|
||||
|
||||
1. **凭空解读:** 没有抓取到原文就开始分析 → 必须至少3条原文
|
||||
2. **只看标题:** 没有读原文段落就下判断 → 必须读核心段落
|
||||
3. **忽略连续性:** 孤立分析单条政策 → 必须串联对比
|
||||
4. **混淆政策类型:** 把财政政策和货币政策混为一谈 → 必须分类
|
||||
5. **过度推断:** 原文没说但分析中写了 → 删除或标注「(推测,非原文)」
|
||||
|
||||
---
|
||||
|
||||
## 9. 一句话调用
|
||||
|
||||
> 「运行政策雷达,搜索{关键词/时间范围},抓取政策原文,按四步法解读,输出 policy-analysis.md。」
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,632 @@
|
||||
"""
|
||||
政策雷达 - 政府网站抓取工具集
|
||||
每个函数返回标准化格式: {"title": str, "date": str, "url": str, "content": str}
|
||||
列表函数返回: [{"title": str, "date": str, "url": str}, ...]
|
||||
"""
|
||||
|
||||
import re
|
||||
import json
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
import ssl
|
||||
from html import unescape
|
||||
|
||||
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||
TIMEOUT = 15
|
||||
|
||||
# 忽略 SSL 证书验证(部分政府站点使用自签名证书)
|
||||
_SSL_CTX = ssl.create_default_context()
|
||||
_SSL_CTX.check_hostname = False
|
||||
_SSL_CTX.verify_mode = ssl.CERT_NONE
|
||||
|
||||
|
||||
def _fetch(url, headers=None):
|
||||
"""通用 HTTP GET,返回解码后的 HTML 文本"""
|
||||
hdrs = {"User-Agent": USER_AGENT}
|
||||
if headers:
|
||||
hdrs.update(headers)
|
||||
req = urllib.request.Request(url, headers=hdrs)
|
||||
with urllib.request.urlopen(req, timeout=TIMEOUT, context=_SSL_CTX) as resp:
|
||||
raw = resp.read()
|
||||
for enc in ("utf-8", "gbk", "gb2312"):
|
||||
try:
|
||||
return raw.decode(enc)
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
return raw.decode("utf-8", errors="replace")
|
||||
|
||||
|
||||
def _extract_paragraphs(html):
|
||||
"""从 HTML 中提取正文段落(通用)"""
|
||||
paragraphs = re.findall(r"<p[^>]*>(.*?)</p>", html, re.DOTALL)
|
||||
result = []
|
||||
for p in paragraphs:
|
||||
text = re.sub(r"<[^>]+>", "", p).strip()
|
||||
text = unescape(text)
|
||||
if text and len(text) > 10:
|
||||
result.append(text)
|
||||
return result
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 优先级 1: 中央政府门户
|
||||
# ============================================================
|
||||
|
||||
def gov_search(keyword, page=1):
|
||||
"""
|
||||
中国政府网 - 搜索 API(可搜索新闻发布会等)
|
||||
URL: https://sousuo.www.gov.cn/search-gov/data?t=zhengcelibrary&q=...
|
||||
返回 JSON,包含 title/url/summary
|
||||
注意: 索引有 1-2 周延迟,最新内容可能尚未收录
|
||||
"""
|
||||
import urllib.parse
|
||||
q = urllib.parse.quote(keyword)
|
||||
api_url = (
|
||||
f"https://sousuo.www.gov.cn/search-gov/data?t=zhengcelibrary"
|
||||
f"&q={q}&p={page}&n=20&timetype=timeqb&mintime=&maxtime="
|
||||
)
|
||||
html = _fetch(api_url)
|
||||
try:
|
||||
data = json.loads(html)
|
||||
except json.JSONDecodeError:
|
||||
return []
|
||||
results = []
|
||||
search_result = data.get("searchVO", {}).get("catMap", {}).get("zhengcelibrary", {})
|
||||
items = search_result.get("listVO", []) if isinstance(search_result, dict) else []
|
||||
for item in items:
|
||||
title = re.sub(r"<[^>]+>", "", item.get("title", "")).strip()
|
||||
url = item.get("url", "")
|
||||
date = item.get("pubtime", "")[:10] if item.get("pubtime") else ""
|
||||
if title and url:
|
||||
results.append({"title": title, "date": date, "url": url})
|
||||
return results
|
||||
|
||||
|
||||
def gov_zhengce_list():
|
||||
"""
|
||||
中国政府网 - 国务院政策文件库
|
||||
URL: https://www.gov.cn/zhengce/
|
||||
结构: 服务端渲染,<li><a href="...">标题</a><span>日期</span></li>
|
||||
"""
|
||||
html = _fetch("https://www.gov.cn/zhengce/")
|
||||
items = re.findall(
|
||||
r'<li>\s*<a href="([^"]+)"[^>]*>\s*([^<]+)\s*</a>\s*<span>\s*([\d-]+)\s*</span>',
|
||||
html,
|
||||
)
|
||||
results = []
|
||||
for url, title, date in items:
|
||||
title = title.strip()
|
||||
if not title:
|
||||
continue
|
||||
if url.startswith("./"):
|
||||
url = "https://www.gov.cn/zhengce/" + url[2:]
|
||||
results.append({"title": title, "date": date, "url": url})
|
||||
return results
|
||||
|
||||
|
||||
def gov_article(url):
|
||||
"""
|
||||
中国政府网 - 政策文章正文
|
||||
正文在 <div class="pages_content"> 内的 <p> 标签中
|
||||
"""
|
||||
html = _fetch(url)
|
||||
# 提取标题
|
||||
title_match = re.search(r'<title>([^<]+)</title>', html)
|
||||
title = title_match.group(1).strip() if title_match else ""
|
||||
# 提取发布日期
|
||||
date_match = re.search(r"发布时间[::]\s*([\d年\-./]+)", html)
|
||||
date = date_match.group(1).strip() if date_match else ""
|
||||
# 提取正文
|
||||
content_paras = _extract_paragraphs(html)
|
||||
return {
|
||||
"title": title,
|
||||
"date": date,
|
||||
"url": url,
|
||||
"content": "\n\n".join(content_paras),
|
||||
}
|
||||
|
||||
|
||||
def scio_press_list():
|
||||
"""
|
||||
国新办 - 新闻发布会文字实录
|
||||
注意: scio.gov.cn 有反爬保护,此处使用 PBC 站点作为镜像
|
||||
PBC 的 "国新办举行新闻发布会" 系列完整保留了国新办原文
|
||||
URL: https://www.pbc.gov.cn/goutongjiaoliu/113456/113469/index.html
|
||||
"""
|
||||
html = _fetch(
|
||||
"https://www.pbc.gov.cn/goutongjiaoliu/113456/113469/index.html"
|
||||
)
|
||||
items = re.findall(
|
||||
r'<a[^>]*href="(/goutongjiaoliu/[^"]+)"[^>]*>([^<]{10,})</a>',
|
||||
html,
|
||||
)
|
||||
results = []
|
||||
seen = set()
|
||||
for href, title in items:
|
||||
title = title.strip()
|
||||
if title and href not in seen and "国新办" in title:
|
||||
seen.add(href)
|
||||
results.append(
|
||||
{
|
||||
"title": title,
|
||||
"date": "",
|
||||
"url": "https://www.pbc.gov.cn" + href,
|
||||
}
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def xinhuanet_list():
|
||||
"""
|
||||
新华社 - 受权发布/时政
|
||||
注意: 使用 www.news.cn(新域名),旧 xinhuanet.com 只有 2021 年旧数据
|
||||
URL: https://www.news.cn/
|
||||
结构: 服务端渲染,标题在 <div class="tit"><a href="URL">标题</a></div>
|
||||
文章链接格式: /{channel}/{YYYYMMDD}/{32-hex}/c.html
|
||||
"""
|
||||
html = _fetch("https://www.news.cn/")
|
||||
pattern = r'<div class="tit"[^>]*><a[^>]*href=[\'"](https?://www\.news\.cn/[^"\']+/20\d{6}/[a-f0-9]{32}/c\.html)[\'"][^>]*>([^<]+)</a>'
|
||||
items = re.findall(pattern, html)
|
||||
results = []
|
||||
seen = set()
|
||||
for url, title in items:
|
||||
title = title.strip()
|
||||
if title and url not in seen:
|
||||
seen.add(url)
|
||||
date_match = re.search(r"/(20\d{6})/", url)
|
||||
date = ""
|
||||
if date_match:
|
||||
d = date_match.group(1)
|
||||
date = f"{d[:4]}-{d[4:6]}-{d[6:8]}"
|
||||
results.append({"title": title, "date": date, "url": url})
|
||||
return results
|
||||
|
||||
|
||||
def xinhuanet_article(url):
|
||||
"""
|
||||
新华社 - 文章正文
|
||||
标题: <h1><span class="title">...</span></h1>
|
||||
正文: <div id="detailContent"> 内的 <p> 标签
|
||||
"""
|
||||
html = _fetch(url)
|
||||
title_match = re.search(r'<h1[^>]*>.*?<span class="title"[^>]*>([^<]+)</span>', html, re.DOTALL)
|
||||
if not title_match:
|
||||
title_match = re.search(r'<title>([^<]+)</title>', html)
|
||||
title = title_match.group(1).strip() if title_match else ""
|
||||
# 提取正文
|
||||
content_match = re.search(r'id="detailContent"[^>]*>(.*?)</div>\s*(?:<div|</)', html, re.DOTALL)
|
||||
if content_match:
|
||||
content_html = content_match.group(1)
|
||||
content_paras = _extract_paragraphs(content_html)
|
||||
else:
|
||||
content_paras = _extract_paragraphs(html)
|
||||
return {
|
||||
"title": title,
|
||||
"date": "",
|
||||
"url": url,
|
||||
"content": "\n\n".join(content_paras),
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 优先级 2: 部委官网
|
||||
# ============================================================
|
||||
|
||||
def pbc_list():
|
||||
"""
|
||||
中国人民银行 - 货币政策/公告/沟通
|
||||
URL: https://www.pbc.gov.cn/goutongjiaoliu/113456/113469/index.html
|
||||
结构: 服务端渲染,<a href="/goutongjiaoliu/...">标题</a>
|
||||
"""
|
||||
html = _fetch(
|
||||
"https://www.pbc.gov.cn/goutongjiaoliu/113456/113469/index.html"
|
||||
)
|
||||
items = re.findall(
|
||||
r'<a[^>]*href="(/goutongjiaoliu/[^"]+)"[^>]*>([^<]{10,})</a>',
|
||||
html,
|
||||
)
|
||||
results = []
|
||||
seen = set()
|
||||
for href, title in items:
|
||||
title = title.strip()
|
||||
if title and href not in seen and len(title) > 5:
|
||||
seen.add(href)
|
||||
# 从 URL 提取日期 (格式: 2026071518015458230)
|
||||
date_match = re.search(r"/(20\d{6})\d{11}/", href)
|
||||
date = ""
|
||||
if date_match:
|
||||
d = date_match.group(1)
|
||||
date = f"{d[:4]}-{d[4:6]}-{d[6:8]}"
|
||||
results.append(
|
||||
{
|
||||
"title": title,
|
||||
"date": date,
|
||||
"url": "https://www.pbc.gov.cn" + href,
|
||||
}
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def pbc_article(url):
|
||||
"""中国人民银行 - 文章正文(正文在 <p> 标签中)"""
|
||||
html = _fetch(url)
|
||||
title_match = re.search(r"<title>([^<]+)</title>", html)
|
||||
title = title_match.group(1).strip() if title_match else ""
|
||||
content_paras = _extract_paragraphs(html)
|
||||
return {
|
||||
"title": title,
|
||||
"date": "",
|
||||
"url": url,
|
||||
"content": "\n\n".join(content_paras),
|
||||
}
|
||||
|
||||
|
||||
def mof_list():
|
||||
"""
|
||||
财政部 - 财政新闻/政策
|
||||
URL: https://www.mof.gov.cn/zhengwuxinxi/caizhengxinwen/
|
||||
结构: 服务端渲染,<a href="t202607...">标题</a> + 日期
|
||||
"""
|
||||
html = _fetch("https://www.mof.gov.cn/zhengwuxinxi/caizhengxinwen/")
|
||||
items = re.findall(
|
||||
r'href="([^"]*t2026[^"]+\.htm)"[^>]*>\s*([^<]{10,80})\s*</a>\s*(?:.*?(\d{4}[-/]\d{2}[-/]\d{2}))?',
|
||||
html,
|
||||
re.DOTALL,
|
||||
)
|
||||
results = []
|
||||
seen = set()
|
||||
for url, title, date in items:
|
||||
title = title.strip()
|
||||
if title and url not in seen:
|
||||
seen.add(url)
|
||||
if url.startswith("./") or url.startswith("t20"):
|
||||
url = "https://www.mof.gov.cn/zhengwuxinxi/caizhengxinwen/" + url.replace("./", "")
|
||||
results.append({"title": title, "date": date or "", "url": url})
|
||||
return results
|
||||
|
||||
|
||||
def mof_article(url):
|
||||
"""财政部 - 文章正文"""
|
||||
html = _fetch(url)
|
||||
title_match = re.search(r"<title>([^<]+)</title>", html)
|
||||
title = title_match.group(1).strip() if title_match else ""
|
||||
date_match = re.search(r"发布日期[::]\s*([\d年\-./]+)", html)
|
||||
date = date_match.group(1).strip() if date_match else ""
|
||||
content_paras = _extract_paragraphs(html)
|
||||
return {
|
||||
"title": title,
|
||||
"date": date,
|
||||
"url": url,
|
||||
"content": "\n\n".join(content_paras),
|
||||
}
|
||||
|
||||
|
||||
def ndrc_list(page=1):
|
||||
"""
|
||||
发改委 - 产业政策/规划
|
||||
URL: https://www.ndrc.gov.cn/xxgk/
|
||||
结构: 服务端渲染,<ul class="u-list"><li><a>标题</a><span>日期(YYYY/MM/DD)</span></li></ul>
|
||||
分页: index_{page-1}.html
|
||||
"""
|
||||
if page == 1:
|
||||
list_url = "https://www.ndrc.gov.cn/xxgk/"
|
||||
else:
|
||||
list_url = f"https://www.ndrc.gov.cn/xxgk/index_{page - 1}.html"
|
||||
html = _fetch(list_url)
|
||||
items = re.findall(
|
||||
r'<a[^>]*href="([^"]+)"[^>]*>\s*([^<]{10,})\s*</a>\s*<span>\s*([\d/]+)\s*</span>',
|
||||
html,
|
||||
)
|
||||
results = []
|
||||
for url, title, date in items:
|
||||
title = title.strip()
|
||||
if not title:
|
||||
continue
|
||||
if url.startswith("./"):
|
||||
url = "https://www.ndrc.gov.cn" + url[1:]
|
||||
results.append({"title": title, "date": date, "url": url})
|
||||
return results
|
||||
|
||||
|
||||
def ndrc_article(url):
|
||||
"""发改委 - 文章正文(正文在 div.TRS_Editor 内)"""
|
||||
html = _fetch(url)
|
||||
title_match = re.search(r"<title>([^<]+)</title>", html)
|
||||
title = title_match.group(1).strip() if title_match else ""
|
||||
editor_match = re.search(r'class="TRS_Editor"[^>]*>(.*?)</div>\s*<', html, re.DOTALL)
|
||||
if editor_match:
|
||||
content_paras = _extract_paragraphs(editor_match.group(1))
|
||||
else:
|
||||
content_paras = _extract_paragraphs(html)
|
||||
return {
|
||||
"title": title,
|
||||
"date": "",
|
||||
"url": url,
|
||||
"content": "\n\n".join(content_paras),
|
||||
}
|
||||
|
||||
|
||||
def csrc_list(page=1):
|
||||
"""
|
||||
证监会 - 主席讲话/政策公告
|
||||
URL: https://www.csrc.gov.cn/csrc/c100028/
|
||||
结构: HTML 页面(API 返回空结果,需用 common/searchList 获取 HTML)
|
||||
HTML URL: /common/searchList/{channelid}?_isAgg=true&_isJson=true&_pageSize=18&_template=index&page={N}
|
||||
"""
|
||||
channel_id = "c100028"
|
||||
url = f"https://www.csrc.gov.cn/common/searchList/{channel_id}?_isAgg=true&_isJson=true&_pageSize=18&_template=index&page={page}"
|
||||
html = _fetch(url)
|
||||
items = re.findall(
|
||||
r'<a[^>]*href="(/csrc/c100028/c\d+/content\.shtml)"[^>]*>([^<]{10,})</a>',
|
||||
html,
|
||||
)
|
||||
results = []
|
||||
seen = set()
|
||||
for path, title in items:
|
||||
title = title.strip()
|
||||
if title and path not in seen:
|
||||
seen.add(path)
|
||||
results.append(
|
||||
{
|
||||
"title": title,
|
||||
"date": "",
|
||||
"url": "https://www.csrc.gov.cn" + path,
|
||||
}
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def csrc_article(url):
|
||||
"""证监会 - 文章正文"""
|
||||
html = _fetch(url)
|
||||
title_match = re.search(r"<title>([^<]+)</title>", html)
|
||||
title = title_match.group(1).strip() if title_match else ""
|
||||
content_paras = _extract_paragraphs(html)
|
||||
return {
|
||||
"title": title,
|
||||
"date": "",
|
||||
"url": url,
|
||||
"content": "\n\n".join(content_paras),
|
||||
}
|
||||
|
||||
|
||||
def mofcom_list():
|
||||
"""
|
||||
商务部 - 外贸/消费政策
|
||||
URL: https://www.mofcom.gov.cn/
|
||||
结构: 政策列表页使用 JSON API
|
||||
API: /api-gateway/jpaas-publish-server/front/page/build/unit
|
||||
"""
|
||||
html = _fetch("https://www.mofcom.gov.cn/")
|
||||
# 首页新闻是 SSR
|
||||
items = re.findall(
|
||||
r'<a[^>]*href="([^"]+)"[^>]*>\s*([^<]{10,80})\s*</a>',
|
||||
html,
|
||||
)
|
||||
results = []
|
||||
seen = set()
|
||||
for url, title in items:
|
||||
title = title.strip()
|
||||
if title and url not in seen and len(title) > 8:
|
||||
seen.add(url)
|
||||
if url.startswith("/"):
|
||||
url = "https://www.mofcom.gov.cn" + url
|
||||
results.append({"title": title, "date": "", "url": url})
|
||||
return results
|
||||
|
||||
|
||||
def mofcom_article(url):
|
||||
"""商务部 - 文章正文(正文在 div.wms-con 内)"""
|
||||
html = _fetch(url)
|
||||
title_match = re.search(r"<title>([^<]+)</title>", html)
|
||||
title = title_match.group(1).strip() if title_match else ""
|
||||
content_match = re.search(r'class="wms-con"[^>]*>(.*?)</div>\s*<', html, re.DOTALL)
|
||||
if content_match:
|
||||
content_paras = _extract_paragraphs(content_match.group(1))
|
||||
else:
|
||||
content_paras = _extract_paragraphs(html)
|
||||
return {
|
||||
"title": title,
|
||||
"date": "",
|
||||
"url": url,
|
||||
"content": "\n\n".join(content_paras),
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 优先级 3: 权威媒体转载
|
||||
# ============================================================
|
||||
|
||||
def people_editorial_list():
|
||||
"""
|
||||
人民日报 - 社论/观点
|
||||
URL: http://opinion.people.com.cn/GB/8213/49160/index.html
|
||||
结构: 主页面有多个子栏目,每个子栏目页面有 <li> 文章列表
|
||||
文章URL格式: /n1/2026/0623/c223228-40745676.html (相对) 或完整URL
|
||||
"""
|
||||
base = "http://opinion.people.com.cn/GB/8213/49160/"
|
||||
html = _fetch(base + "index.html")
|
||||
# 获取所有子栏目链接(完整URL)
|
||||
sub_urls = re.findall(r'href="(http://opinion\.people\.com\.cn/GB/8213/49160/\d+/index\.html)"', html)
|
||||
sub_urls = list(dict.fromkeys(sub_urls))
|
||||
results = []
|
||||
seen = set()
|
||||
for sub in sub_urls:
|
||||
try:
|
||||
sub_html = _fetch(sub)
|
||||
# 解析 <li> 项目(注意:人民网的链接使用单引号 href='...')
|
||||
lis = re.findall(r"<li[^>]*>(.*?)</li>", sub_html, re.DOTALL)
|
||||
for li in lis:
|
||||
# 匹配单引号或双引号的 href
|
||||
m = re.search(r"href=['\"](/n1/\d{4}/\d{4}/c[\d-]+\.html)['\"][^>]*>([^<]{10,})</a>", li)
|
||||
if m:
|
||||
url_path, title = m.groups()
|
||||
title = title.strip()
|
||||
url = "http://opinion.people.com.cn" + url_path
|
||||
if title and url not in seen:
|
||||
seen.add(url)
|
||||
date_match = re.search(r"/n1/(20\d{2})/(\d{4})/", url)
|
||||
date = ""
|
||||
if date_match:
|
||||
year, md = date_match.groups()
|
||||
date = f"{year}-{md[:2]}-{md[2:]}"
|
||||
results.append({"title": title, "date": date, "url": url})
|
||||
except Exception:
|
||||
continue
|
||||
return results
|
||||
|
||||
|
||||
def people_article(url):
|
||||
"""人民日报 - 文章正文(正文在 <p> 标签中,class=rm_txt_zw 的容器内)"""
|
||||
html = _fetch(url)
|
||||
title_match = re.search(r"<title>([^<]+)</title>", html)
|
||||
title = title_match.group(1).strip() if title_match else ""
|
||||
# 正文在 p 标签中
|
||||
content_paras = _extract_paragraphs(html)
|
||||
return {
|
||||
"title": title,
|
||||
"date": "",
|
||||
"url": url,
|
||||
"content": "\n\n".join(content_paras),
|
||||
}
|
||||
|
||||
|
||||
def cctv_list(page=1):
|
||||
"""
|
||||
央视新闻 - 新闻联播文字版
|
||||
URL: https://news.cctv.com/lbj/
|
||||
结构: JSONP API
|
||||
API: https://news.cctv.com/2019/07/gaiban/cmsdatainterface/page/china_{page}.jsonp?callback=china
|
||||
注意: 需要设置 Referer 头
|
||||
"""
|
||||
api_url = f"https://news.cctv.com/2019/07/gaiban/cmsdatainterface/page/china_{page}.jsonp?callback=china"
|
||||
raw = _fetch(api_url, headers={"Referer": "https://news.cctv.com/"})
|
||||
# 解析 JSONP: china({...})
|
||||
json_match = re.search(r"[^(]+\((\{.*\})\)", raw, re.DOTALL)
|
||||
if not json_match:
|
||||
return []
|
||||
try:
|
||||
data = json.loads(json_match.group(1))
|
||||
except json.JSONDecodeError:
|
||||
return []
|
||||
items = data.get("data", {}).get("list", []) if isinstance(data.get("data"), dict) else []
|
||||
results = []
|
||||
for item in items:
|
||||
title = item.get("title", "").strip()
|
||||
url = item.get("url", item.get("link", ""))
|
||||
date = item.get("focus_date", item.get("date", ""))
|
||||
if title and url:
|
||||
results.append(
|
||||
{
|
||||
"title": title,
|
||||
"date": str(date)[:10],
|
||||
"url": url,
|
||||
}
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def cctv_article(url):
|
||||
"""央视新闻 - 文章正文(正文在 div.content_area 内)"""
|
||||
html = _fetch(url)
|
||||
title_match = re.search(r"<title>([^<]+)</title>", html)
|
||||
title = title_match.group(1).strip() if title_match else ""
|
||||
content_match = re.search(r'class="content_area"[^>]*>(.*?)</div>\s*<', html, re.DOTALL)
|
||||
if content_match:
|
||||
content_paras = _extract_paragraphs(content_match.group(1))
|
||||
else:
|
||||
content_paras = _extract_paragraphs(html)
|
||||
return {
|
||||
"title": title,
|
||||
"date": "",
|
||||
"url": url,
|
||||
"content": "\n\n".join(content_paras),
|
||||
}
|
||||
|
||||
|
||||
def ce_list():
|
||||
"""
|
||||
经济日报 - 部委政策解读
|
||||
URL: http://www.ce.cn/
|
||||
结构: 服务端渲染,文章链接格式: /xwzx/gnsz/gdxw/202607/t20260721_xxxxxxx.shtml
|
||||
政策相关文章在 /gnsz/ (国内时政) 和 /xwzx/ (新闻) 栏目下
|
||||
"""
|
||||
html = _fetch("http://www.ce.cn/")
|
||||
items = re.findall(
|
||||
r'<a[^>]*href="([^"]*t2026[^"]+\.shtml)"[^>]*>([^<]{10,})</a>',
|
||||
html,
|
||||
)
|
||||
results = []
|
||||
seen = set()
|
||||
for url, title in items:
|
||||
title = title.strip()
|
||||
# 过滤政策相关文章(国内时政/新闻栏目)
|
||||
if "/gnsz/" not in url and "/xwzx/" not in url and "/syj/" not in url:
|
||||
continue
|
||||
if title and url not in seen:
|
||||
seen.add(url)
|
||||
if url.startswith("/"):
|
||||
url = "http://www.ce.cn" + url
|
||||
# 从 URL 提取日期
|
||||
date_match = re.search(r"/(20\d{6})/", url)
|
||||
date = ""
|
||||
if date_match:
|
||||
d = date_match.group(1)
|
||||
date = f"{d[:4]}-{d[4:6]}-{d[6:8]}"
|
||||
results.append({"title": title, "date": date, "url": url})
|
||||
return results
|
||||
|
||||
|
||||
def ce_article(url):
|
||||
"""经济日报 - 文章正文(正文在 div.content.clearfix 内)"""
|
||||
html = _fetch(url)
|
||||
title_match = re.search(r'id="NewsArticleTitle"[^>]*>([^<]+)', html)
|
||||
if not title_match:
|
||||
title_match = re.search(r"<title>([^<]+)</title>", html)
|
||||
title = title_match.group(1).strip() if title_match else ""
|
||||
content_match = re.search(r'class="content clearfix"[^>]*>(.*?)</div>\s*<', html, re.DOTALL)
|
||||
if content_match:
|
||||
content_paras = _extract_paragraphs(content_match.group(1))
|
||||
else:
|
||||
content_paras = _extract_paragraphs(html)
|
||||
return {
|
||||
"title": title,
|
||||
"date": "",
|
||||
"url": url,
|
||||
"content": "\n\n".join(content_paras),
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 统一入口
|
||||
# ============================================================
|
||||
|
||||
SCRAPERS = {
|
||||
"gov.cn": {"list": gov_zhengce_list, "article": gov_article, "name": "中国政府网"},
|
||||
"xinhuanet": {"list": xinhuanet_list, "article": xinhuanet_article, "name": "新华社"},
|
||||
"pbc": {"list": pbc_list, "article": pbc_article, "name": "中国人民银行"},
|
||||
"mof": {"list": mof_list, "article": mof_article, "name": "财政部"},
|
||||
"ndrc": {"list": ndrc_list, "article": ndrc_article, "name": "发改委"},
|
||||
"csrc": {"list": csrc_list, "article": csrc_article, "name": "证监会"},
|
||||
"mofcom": {"list": mofcom_list, "article": mofcom_article, "name": "商务部"},
|
||||
"people": {"list": people_editorial_list, "article": people_article, "name": "人民日报"},
|
||||
"cctv": {"list": cctv_list, "article": cctv_article, "name": "央视新闻"},
|
||||
"ce": {"list": ce_list, "article": ce_article, "name": "经济日报"},
|
||||
"scio": {"list": scio_press_list, "article": pbc_article, "name": "国新办(PBC镜像)"},
|
||||
}
|
||||
|
||||
|
||||
def scrape_list(site_key, **kwargs):
|
||||
"""统一列表抓取入口"""
|
||||
scraper = SCRAPERS.get(site_key)
|
||||
if not scraper:
|
||||
return []
|
||||
return scraper["list"](**kwargs)
|
||||
|
||||
|
||||
def scrape_article(site_key, url):
|
||||
"""统一文章抓取入口"""
|
||||
scraper = SCRAPERS.get(site_key)
|
||||
if not scraper:
|
||||
return {"title": "", "date": "", "url": url, "content": ""}
|
||||
return scraper["article"](url)
|
||||
Reference in New Issue
Block a user