# 每日行情

整合 PM001 论坛抓取与纪念币/钞价格解析，每日生成行情 Excel、趋势数据库与静态展示页面。

## 功能

- 抓取 PM001 论坛板块 10（纪念币）和 151（纪念钞）的当日帖子
- 过滤标题或正文含「收/收购/求/求购」的帖子，排除「出售」帖
- 对正文执行结构化价格解析：
  - 纪念币：盒价/卷价/散新价/卡册价
  - 纪念钞：标十/标百/刀/散张/捆，支持号码修饰（带4/无4/无47/无347）和价格范围
- 产出双工作表 Excel（板块10/151 分别一个工作表）
- SQLite 存储每日价格，支持趋势查询
- 静态 HTML 页面（Vue3 + shadcn-vue violet 主题）：
  - 价格列表表格，支持搜索和表头排序
  - 点击品种查看近期行情折线图
  - 来源链接 hover 显示原帖标题
  - 深色/浅色模式切换

## 快速开始

### 本地运行

```bash
cd 每日行情
pip install -r requirements.txt

# 抓取当日行情（板块 10 和 151）
python run.py

# 或指定参数
python run.py --boards 10        # 仅抓纪念币
python run.py --boards 151       # 仅抓纪念钞
python run.py --date 2026-08-12  # 指定日期
python run.py --force            # 强制重抓（忽略幂等检查）
python run.py --sample --boards 151  # 样本模式（不解析价格）
```

### 本地预览页面

```bash
python -m http.server 8765
# 浏览器访问 http://localhost:8765/site/index.html
```

## 服务器部署（Ubuntu/Debian）

### 一键部署

```bash
# 克隆或上传项目到服务器后执行
sudo bash deploy/install.sh
```

部署脚本会自动完成：
1. 安装系统依赖（python3, caddy）
2. 创建部署用户 `daily-market`
3. 部署代码到 `/opt/daily-market`
4. 创建 Python 虚拟环境并安装依赖
5. 配置 systemd 服务：
   - `daily-market-web.service` — Web 静态服务（127.0.0.1:8765）
   - `daily-market-crawl.timer` — 每日定时抓取（北京时间 10:00 和 16:00）
6. 配置 Caddy 反向代理（80 端口 → 127.0.0.1:8765）

### 自定义部署参数

```bash
# 指定部署用户
sudo DEPLOY_USER=www bash deploy/install.sh

# 跳过 Caddy 配置（已有 Caddy 或使用其他反代）
sudo SKIP_CADDY=1 bash deploy/install.sh
```

### 访问

部署完成后：
- **站点首页**：`http://服务器IP/site/index.html`
- **当日行情**：`http://服务器IP/data/daily/YYYY-MM-DD/index.html`

### 使用域名和 HTTPS

编辑 `/etc/caddy/Caddyfile`，将 `:80` 改为域名：

```
your-domain.com {
    reverse_proxy 127.0.0.1:8765
}
```

重启 Caddy：`sudo systemctl restart caddy`（Caddy 会自动申请 Let's Encrypt 证书）

## 常用运维命令

```bash
# 手动触发抓取
sudo -u daily-market /opt/daily-market/.venv/bin/python /opt/daily-market/run.py

# 查看抓取日志
journalctl -u daily-market-crawl -f

# 查看 Web 服务日志
journalctl -u daily-market-web -f

# 查看定时任务状态
systemctl list-timers daily-market-crawl

# 重启 Web 服务
sudo systemctl restart daily-market-web

# 暂停/恢复定时抓取
sudo systemctl stop daily-market-crawl.timer
sudo systemctl start daily-market-crawl.timer

# 查看 Caddy 日志
journalctl -u caddy -f
```

## 项目结构

```
每日行情/
├── run.py                  # 主入口
├── requirements.txt        # Python 依赖
├── src/
│   ├── config.py           # 配置（板块、路径、HTTP 参数）
│   ├── db.py               # SQLite 数据库操作
│   ├── fetcher.py          # 论坛 HTTP 抓取器
│   ├── daily_crawler.py    # 当日帖子抓取与关键字匹配
│   ├── excel_exporter.py   # 双工作表 Excel 导出
│   ├── html_reporter.py    # Vue3 静态页面生成
│   └── parsers/
│       ├── base.py         # PriceRecord 数据结构
│       ├── coin_parser.py  # 纪念币价格解析（板块10）
│       └── banknote_parser.py  # 纪念钞价格解析（板块151）
├── deploy/                 # 部署配置
│   ├── install.sh          # 一键部署脚本
│   ├── daily-market-web.service    # Web 服务 systemd 配置
│   ├── daily-market-crawl.service  # 抓取任务 systemd 配置
│   ├── daily-market-crawl.timer    # 定时触发器配置
│   └── Caddyfile.example   # Caddy 反向代理配置示例
├── data/
│   ├── market.db           # SQLite 趋势数据库
│   ├── samples/            # 抓取样本
│   └── daily/              # 每日 Excel + 静态页面
└── site/
    └── index.html          # 日期索引页
```

## 命令行参数

| 参数 | 说明 | 默认值 |
|------|------|--------|
| `--date YYYY-MM-DD` | 抓取日期 | 今天（Asia/Shanghai） |
| `--boards 10,151` | 逗号分隔的板块ID | 10,151 |
| `--sample` | 样本模式：仅抓取不解析 | 关闭 |
| `--force` | 强制重抓，忽略幂等检查 | 关闭 |
| `--max-pages N` | 每个板块最大翻页数 | 10 |
