zhaojunlong fb70356f5d
All checks were successful
Deploy Vue App / build-and-deploy (push) Successful in 8s
```
ci(deploy): 更新部署分支为南京公共资源交易中心

将 Gitea 工作流中的触发分支从 master 更新为南京公共资源交易中心,
以确保代码变更能够正确部署到指定环境。
```
2025-12-16 09:33:20 +08:00
```
2025-12-16 09:33:20 +08:00
```
2025-12-15 21:06:10 +08:00
```
2025-12-15 21:06:10 +08:00
```
2025-12-15 15:58:48 +08:00
```
2025-12-15 15:58:48 +08:00
```
2025-12-15 21:06:10 +08:00
```
2025-12-15 15:58:48 +08:00

南京公共工程建设中心 - 公告采集工具

一个用于采集南京公共工程建设中心公告信息的 Web 可视化工具,支持定时任务和邮件推送。

功能特性

  • 采集公告列表(支持分页)
  • 按时间范围智能采集
  • 采集公告详情内容
  • 智能提取预算金额
  • 生成统计报告
  • Web 可视化界面
  • 导出 Word/Markdown 报告
  • RESTful API 支持
  • 定时任务自动采集
  • 邮件推送 HTML 报告
  • Web 配置界面
  • 无需数据库,轻量部署

快速开始

1. 安装依赖

npm install

2. 配置文件

首次使用需要创建配置文件:

# 复制示例配置文件
cp config.example.json config.json

# 编辑配置文件(或通过 Web 界面配置)
# 填写邮件服务器信息和定时任务设置

配置文件说明:

  • config.example.json - 配置模板(不含敏感信息,可提交到 Git
  • config.json - 实际配置(包含密码等敏感信息,已在 .gitignore 中忽略)

使用方法

1. 启动服务器

npm start

2. 访问界面

打开浏览器访问: http://localhost:5000 (或您配置的端口)

3. 功能介绍

公告列表标签

  • 快速查看所有公告
  • 支持分页浏览
  • 一键获取最新公告列表

详情采集标签

  • 批量采集公告详情
  • 支持按时间范围采集
  • 自动提取预算金额
  • 可自定义采集数量

生成报告标签

  • 支持按时间范围生成报告
  • 设置金额阈值筛选项目
  • 实时统计项目信息
  • 一键导出 Word/Markdown 报告

定时任务标签 新增

  • Web 界面配置定时任务
  • 支持 Cron 表达式自定义执行时间
  • 可选时间范围(今日/本周/本月)
  • 设置金额阈值自动筛选
  • 实时查看任务运行状态
  • 立即测试运行功能

邮件配置标签 新增

  • Web 界面配置 SMTP 邮件服务
  • 支持主流邮箱QQ、163、Gmail 等)
  • 测试连接功能验证配置
  • 支持多个收件人
  • 自动发送精美 HTML 报告

报告示例

# 南京公共工程建设项目报告

**生成时间**: 2025/12/12 11:00:03

## 统计摘要

- 总项目数: 10
- 超过 50 万元的项目: 3
- 总金额: 5395.50 万元

## 项目列表

### 1. 项目名称

- **发布日期**: 2025-12-12
- **发布时间**: 2025-12-12 10:35:00
- **预算金额**: 5000 万元
- **链接**: https://...

API 接口文档

服务器启动后提供以下 RESTful API 接口:

1. 获取公告列表

GET /api/list?url=<列表页URL>&page=<页码>

参数:

  • url (可选): 列表页 URL,默认为官网首页
  • page (可选): 页码,默认为 1

2. 按时间范围获取列表

POST /api/list-daterange
Content-Type: application/json

{
  "startDate": "2025-11-01",
  "endDate": "2025-12-31",
  "maxPages": 23
}

3. 批量获取详情

POST /api/details
Content-Type: application/json

{
  "items": [{ "title": "...", "href": "...", "date": "..." }],
  "limit": 10
}

4. 生成报告

POST /api/report
Content-Type: application/json

{
  "url": "https://gjzx.nanjing.gov.cn/gggs/",
  "limit": 15,
  "threshold": 50
}

5. 按时间范围生成报告

POST /api/report-daterange
Content-Type: application/json

{
  "startDate": "2025-11-01",
  "endDate": "2025-12-31",
  "threshold": 50,
  "maxPages": 23
}

6. 获取配置

GET /api/config

返回当前配置信息(密码会被隐藏)

7. 更新配置

POST /api/config
Content-Type: application/json

{
  "scheduler": {
    "enabled": true,
    "cronTime": "0 9 * * *",
    "threshold": 100000,
    "timeRange": "today"
  },
  "email": {
    "smtpHost": "smtp.qq.com",
    "smtpPort": 587,
    "smtpUser": "your-email@qq.com",
    "smtpPass": "your-password",
    "recipients": "recipient@example.com"
  }
}

8. 获取定时任务状态

GET /api/scheduler/status

9. 手动触发定时任务

POST /api/run-scheduled-task

定时任务配置

通过 Web 界面配置(推荐)

  1. 访问 http://localhost:5000 (或您配置的端口)
  2. 切换到 "定时任务" 标签
  3. 配置以下选项:
    • 启用定时任务:勾选启用
    • 执行时间:选择预设时间或自定义 Cron 表达式
    • 时间范围:今日/本周/本月
    • 金额阈值:设置最低金额(单位:万元)
  4. 切换到 "邮件配置" 标签
  5. 配置 SMTP 邮件服务器信息
  6. 点击"测试连接"验证配置
  7. 点击"保存配置",定时任务自动生效

通过配置文件

编辑 config.json

{
  "scheduler": {
    "enabled": true,              // 是否启用
    "cronTime": "0 9 * * *",      // Cron表达式每天9点
    "threshold": 100000,           // 金额阈值万元10亿
    "description": "每天9点采集大于10亿的项目",
    "timeRange": "today"           // 采集范围: today/thisWeek/thisMonth
  },
  "email": {
    "smtpHost": "smtp.qq.com",    // SMTP服务器
    "smtpPort": 587,               // 端口
    "smtpUser": "your@qq.com",     // 发件邮箱
    "smtpPass": "授权码",           // QQ邮箱授权码
    "recipients": "to@qq.com"      // 收件人(多个用逗号分隔)
  }
}

Cron 表达式说明

格式:分 时 日 月 周

常用示例:

  • 0 9 * * * - 每天 9:00
  • 0 9,18 * * * - 每天 9:00 和 18:00
  • 0 9 * * 1 - 每周一 9:00
  • 0 9 1 * * - 每月1号 9:00
  • 0 */6 * * * - 每 6 小时

邮件服务配置参考

QQ 邮箱:

  • SMTP: smtp.qq.com
  • 端口: 587
  • 密码: 使用授权码(在 QQ 邮箱设置中生成)

163 邮箱:

  • SMTP: smtp.163.com
  • 端口: 465
  • 密码: 使用授权码

Gmail

  • SMTP: smtp.gmail.com
  • 端口: 587
  • 需要开启"不够安全的应用访问"

服务器部署

方法 1使用 PM2推荐

# 安装 PM2
npm install -g pm2

# 启动服务
pm2 start src/server.js --name gjzx-scraper

# 查看状态
pm2 status

# 查看日志
pm2 logs gjzx-scraper

# 设置开机自启
pm2 startup
pm2 save

方法 2使用 systemd

创建服务文件 /etc/systemd/system/gjzx-scraper.service

[Unit]
Description=GJZX Scraper Service
After=network.target

[Service]
Type=simple
User=your-user
WorkingDirectory=/path/to/tool-node
ExecStart=/usr/bin/node src/server.js
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

启动服务:

sudo systemctl enable gjzx-scraper
sudo systemctl start gjzx-scraper
sudo systemctl status gjzx-scraper

注意事项

  • 无需数据库:项目采用无数据库架构,轻量部署
  • 配置持久化:所有配置保存在 config.json 文件中
  • 进程保活:使用 PM2 或 systemd 确保进程持续运行
  • ⚠️ 防火墙:确保配置的端口可访问(默认 5000
  • ⚠️ 配置安全:不要将 config.json 提交到公开仓库

技术栈

  • 后端: Node.js + Express
  • 爬虫: Axios + Cheerio
  • 定时任务: node-cron
  • 邮件服务: nodemailer
  • 前端: 原生 HTML/CSS/JavaScript
  • 编码处理: iconv-lite (支持 GBK/UTF-8)
  • 文档导出: docx.js
  • 架构: 无数据库设计

项目结构

.
├── src/
│   ├── server.js         # Web服务器及API
│   ├── scheduler.js      # 定时任务调度器
│   └── emailService.js   # 邮件发送服务
├── public/
│   ├── index.html        # Web界面
│   └── app.js           # 前端逻辑
├── config.json          # 配置文件不提交到Git
├── config.example.json  # 配置示例
├── package.json
└── README.md

架构特点

无数据库设计

本项目采用无数据库架构,具有以下特点:

  • 轻量部署:无需安装和配置数据库
  • 实时数据:每次从源站实时抓取最新数据
  • 配置简单:只需配置 config.json 文件
  • 邮件归档:报告通过邮件发送,邮箱即为历史记录
  • 低资源消耗:内存占用小,适合小型服务器

数据流程

定时触发 → 抓取网站数据 → 解析提取 → 筛选过滤 → 生成报告 → 发送邮件
   ↑                                                        ↓
   └──────────────────── 配置文件 ──────────────────────────┘

注意事项

  1. 采集速度:已限制为每条延迟 500ms-1s避免请求过快
  2. 域名支持:仅支持 gjzx.nanjing.gov.cn 域名的详情页解析
  3. 金额提取:基于正则匹配,支持多种格式(预算金额、最高限价等)
  4. 端口配置Web 服务器默认端口 5000支持通过环境变量 PORT 修改
  5. 智能停止:按时间范围采集会在检测到所有公告早于起始日期时自动停止
  6. 编码处理:自动识别,支持 GBK 和 UTF-8 网页
  7. 配置安全config.json 包含敏感信息,已加入 .gitignore不要提交到公开仓库
  8. 进程保活:部署时使用 PM2 或 systemd 确保定时任务持续运行

核心功能说明

时间范围采集逻辑

按时间范围采集时,程序会:

  1. 从第一页开始顺序采集
  2. 检查每页公告的日期是否在指定范围内
  3. 如果某页所有公告都早于起始日期,自动停止采集
  4. 支持设置最大页数限制,避免过度采集

金额提取规则

支持识别以下格式:

  • 预算金额: XX 万元
  • 最高限价: XX 万元
  • 预算: XX 万元
  • 金额: XX 万元
  • 直接数字: XX 万元

编码处理

自动识别网页编码:

  • 优先读取 Content-Type 中的 charset
  • 自动处理 GBK、GB2312 编码
  • 默认使用 UTF-8

常见问题

Q: 为什么采集速度比较慢?

A: 为了避免对服务器造成过大压力,程序限制了请求频率(每条延迟 500ms-1s。这是一个负责任的爬虫设计。

Q: 如何采集指定日期范围的公告?

A: 在 Web 界面的"详情采集"和"生成报告"标签中勾选"按时间范围采集",然后输入起始和结束日期即可。

Q: 导出的报告在哪里?

A: 点击"导出 Word"或"导出 Markdown"按钮后会自动下载到浏览器的默认下载目录。

Q: 可以采集其他网站吗?

A: 需要修改 server.js 中的 BASE_URL 和相应的解析函数,因为不同网站的 HTML 结构不同。

Q: 需要安装数据库吗?

A: 不需要! 本项目采用无数据库架构,只需安装 Node.js 依赖即可运行。所有配置保存在 config.json 文件中,报告通过邮件发送。

Q: 定时任务配置后不生效怎么办?

A: 请检查以下几点:

  1. config.jsonscheduler.enabled 是否为 true
  2. 邮件配置是否正确SMTP 服务器、用户名、密码)
  3. Node.js 进程是否持续运行(使用 PM2 查看状态)
  4. 查看服务器日志是否有错误信息

Q: 如何修改定时任务的执行时间?

A: 有两种方式:

  1. Web 界面(推荐):访问网页,切换到"定时任务"标签,选择预设时间或自定义 Cron 表达式,点击保存
  2. 配置文件:编辑 config.json 中的 scheduler.cronTime 字段

Q: 邮件发送失败怎么办?

A: 常见原因:

  1. QQ 邮箱:需要使用授权码,不是登录密码(在 QQ 邮箱设置 → 账户 → POP3/SMTP 服务中生成)
  2. 端口问题QQ 邮箱使用 587某些邮箱可能需要 465SSL
  3. 防火墙:确保服务器可以访问 SMTP 端口
  4. 测试连接:在"邮件配置"标签中使用"测试连接"功能验证配置

Q: 如何查看定时任务运行日志?

A: 如果使用 PM2 部署:

pm2 logs gjzx-scraper

如果使用 systemd

sudo journalctl -u gjzx-scraper -f

Q: 服务器重启后定时任务还会运行吗?

A: 需要设置开机自启:

  • PM2 方式:执行 pm2 startuppm2 save
  • systemd 方式:执行 sudo systemctl enable gjzx-scraper

Q: 可以设置多个定时任务吗?

A: 当前版本只支持一个定时任务。如需多个任务,可以:

  1. 使用 Cron 表达式设置多个时间点(如 0 9,18 * * * 表示每天 9:00 和 18:00
  2. 部署多个实例,使用不同的配置文件和端口

更新日志

v1.1.0 (2025-12-15)

  • 新增定时任务功能node-cron
  • 新增邮件推送服务nodemailer
  • 新增 Web 配置界面(定时任务 + 邮件配置)
  • 支持多时间范围(今日/本周/本月)
  • 配置 API读取/更新配置)
  • 定时任务状态查询
  • 手动触发任务功能
  • 📝 完善文档,新增部署指南

v1.0.0 (2025-12-12)

  • Web 可视化界面
  • 支持按时间范围采集
  • 支持分页浏览
  • 支持导出 Word/Markdown 报告
  • RESTful API 接口
  • 自动编码识别
  • 智能金额提取

License

MIT

Description
No description provided
Readme 4.3 MiB
Languages
JavaScript 75.3%
HTML 24.7%