# Python脚本说明

## 目录结构

```
python/
├── README.md                      # 本文件
├── requirements.txt               # Python依赖列表
├── requirements_minimal.txt       # 最小依赖（仅PyMuPDF）
├── install.bat                    # Windows安装脚本
├── install.sh                     # Linux/macOS安装脚本
├── check_template_structure.py   # 检查Word模板结构
├── company_particulars_detector.py # 香港查册文件检测（PyMuPDF提取文本，扫描版fallback百度OCR）
├── credit_report_detector.py     # 检测企业信用报告
├── debug_pdf_pages.py            # 调试PDF页面
├── extract_placeholders.py       # 提取Word占位符
├── keep_first_pages.py           # 保留PDF前N页
├── normalize_pdf.py              # PDF标准化
├── qrcode.py                     # 二维码提取
├── qrcode_opencv.py              # 二维码提取（OpenCV变体）
├── qrcode_unicode_safe.py        # 二维码提取（Unicode路径安全变体）
├── qrcode_universal.py           # 二维码提取（多算法兼容变体）
├── remove_blank_pages.py         # 删除空白页
├── remove_pdf_page.py            # 删除指定页面
├── rpa_030_get.py                # RPA 030 取数脚本（读取 AsyncVATTasks 任务记录）
└── rpa_030_save.py               # RPA 030 保存脚本（按 DataSource 分流写结果/回调）
```

## 快速开始

### 1. 安装依赖

**Windows**:
```bash
cd python
install.bat
```

**Linux/macOS**:
```bash
cd python
chmod +x install.sh
./install.sh
```

**手动安装**:
```bash
pip install -r requirements.txt
```

**最小安装**（仅PDF处理，不需要二维码功能）:
```bash
pip install -r requirements_minimal.txt
```

### 2. 验证安装

```bash
python -c "import fitz; print('PyMuPDF installed!')"
```

## 脚本说明

### PDF处理脚本

#### 1. normalize_pdf.py - PDF标准化
将PDF标准化为A4尺寸

```bash
python normalize_pdf.py input.pdf output.pdf
```

**依赖**: PyMuPDF

#### 2. remove_pdf_page.py - 删除指定页面
删除PDF的指定页面

```bash
# 删除第4页
python remove_pdf_page.py input.pdf output.pdf 4

# 删除多页
python remove_pdf_page.py input.pdf output.pdf 3 4 5
```

**依赖**: PyMuPDF

#### 3. remove_blank_pages.py - 删除空白页
自动删除PDF中的空白页

```bash
python remove_blank_pages.py input.pdf output.pdf
```

**依赖**: PyMuPDF

#### 4. keep_first_pages.py - 保留前N页
保留PDF的前N页，丢弃其余页面

```bash
python keep_first_pages.py input.pdf output.pdf N
```

**依赖**: PyPDF2 / pypdf

#### 5. debug_pdf_pages.py - 调试PDF
显示PDF每一页的内容

```bash
python debug_pdf_pages.py input.pdf
```

**依赖**: PyMuPDF

#### 6. credit_report_detector.py - 检测企业信用报告
检测PDF是否为企业信用报告

```bash
python credit_report_detector.py input.pdf
```

**依赖**: PyMuPDF

#### 7. company_particulars_detector.py - 香港查册文件检测
检测PDF是否为香港公司查册文件（Company Particulars）。两阶段检测的第一阶段：PyMuPDF提取文本与关键词匹配（Company Particulars、公司资料等）；文本提取不到（扫描版）时由 `VATDataService::isCompanyParticularsPDF` fallback 到百度OCR。

```bash
python company_particulars_detector.py input.pdf
```

**依赖**: PyMuPDF

### Word模板脚本

#### 8. extract_placeholders.py - 提取占位符
从Word模板中提取所有占位符

```bash
python extract_placeholders.py template.docx
```

**依赖**: 无（使用标准库）

#### 9. check_template_structure.py - 检查模板结构
检查Word模板的XML结构

```bash
python check_template_structure.py template.docx
```

**依赖**: 无（使用标准库）

### 图像处理脚本

#### 10. qrcode.py - 二维码提取
从PDF中提取二维码

```bash
python qrcode.py input.pdf qrcode.png 0
```

**依赖**: PyMuPDF, Pillow, opencv-python, numpy, pyzbar

**注意**: 需要系统安装zbar库

变体脚本（同一用途的不同兼容实现）：
- `qrcode_opencv.py` - OpenCV 解码变体
- `qrcode_unicode_safe.py` - Unicode 路径安全变体
- `qrcode_universal.py` - 多算法兼容变体

### RPA 030 脚本（服务器端）

#### 11. rpa_030_get.py - 030 取数
读取 `AsyncVATTasks` 任务记录（兼容 LegalSignedFile 的 JSON 串/完整 URL/F_Id 三种格式，`Code`→`BusinessCode` 兜底），供 RPA 程序生成 030 文件。

API 流程 usaeu 桶为私有桶、下载需带验证信息：`query_and_update_vat_task` / `process_legal_signed_file` 分开传 COS 凭证参数（`secret_id`、`secret_key`、`bucket`、`region`）时，对 API 流程解析出的完整 URL 生成 COS 签名 URL（600 秒，`sign_cos_url` 仿 PHP `CosDownloader::signBucketUrl`）；未传/签名失败兜底无签名直连（公读对象仍可用）。OSS 基础地址不再作为参数传入，固定在文件级常量 `DEFAULT_OSS_BASE_URL`（usaeu）。

**签名 URL 下载陷阱（2026-08-29 线上问题）**：COS 签名 URL 绑定 GET 方法——对签名 URL 发 **HEAD（获取文件信息）必 403 Forbidden**（表现：RPA 程序【http下载文件】"获取文件信息失败"后降级仅提取文件名，造成下载失败但流程继续）。下载前探测/获取文件信息须用 **GET + `Range: bytes=0-0`**（200/206 即对象存在，Content-Range 头可取对象总大小；`probe_cos_object()` 已实现）。另注意签名有效期 600 秒，RPA 程序取数与下载之间耗时过长（重试/排队）导致签名过期也会 403——此时需重新调用取数流程获取新签名。

**依赖**: pymssql

#### 12. rpa_030_save.py - 030 保存
按任务 `DataSource` 分流：`api` → 不写 vat_db 附件表，只更新任务记录（pdf030_result=2/3、pdf030_result_url、ResultData merge pdf030_url）并调用对方结果通知接口（成功 `data.files` 文件数组：海牙文件-已认证 + 其他推送文件，失败 `data=null`、错误原因放 `msg`）；`source` → 原逻辑（写 Base_AnnexesFile）不变。

API 流程上传桶按 COS 桶分流（API 与 source 桶不同）：`api_bucket_name` 参数（可选）> 默认 usaeu-1259285998（SaaS 共享桶）；RPA 进程环境与项目 `.env` 隔离，不读环境变量，覆盖通道只有脚本参数。

**API 流程相对路径契约（2026-08-31）**：COS 对象键 = 文件级常量 `API_FLOW_OSS_PREFIX`（`common-test/generatefile/` 或 `common-prod/generatefile/`，年份文件夹之前的部分，部署到对应服务器时保持对应环境）+ 当前年份 + 子目录常量 `API_FLOW_OSS_MODULE_DIR`（`es_vat_haiya`）+ 文件名，即 `{前缀}{当前年}/es_vat_haiya/{文件名}`（不再含时间戳子文件夹；海牙合并 PDF 与 030 文件同目录存放，文件命名不变）。入库（pdf030_result_url / ResultData.cos_url）与结果通知 `files[].url`（海牙+030）均为该相对路径——不带域名、不再生成 COS 签名 URL，域名由接收方拼接；source 流程原逻辑不变（cos_path + 时间戳文件夹 + 完整 URL，公读桶无签名 URL）。

**独立程序约束（2026-08-29 线上问题）**：OctopusRPA 中取数与保存是两个相互独立的流程，各自编译为 `running_temp` 下独立的 `rpa.py`，跨文件 import 报 `ModuleNotFoundError`；两个脚本各自必须自包含，禁止相互 import。COS 签名函数（`sign_cos_url` / `build_cos_client` / `build_signed_cos_url`）仅 rpa_030_get.py（取数流程下载输入文件）保留；rpa_030_save.py 已随结果通知改相对路径将其移除。

**通知结果即时落库（2026-08-29 线上问题）**：回调地址填错导致超时时，此前要等全部 4 次重试（约 55 秒阻塞）结束才写一次 Notify* 字段，期间 RPA 流程被中断/步骤超时杀进程则字段全空、无任何排查线索。现在 `notify_api_result` 通过 `persist` 回调**每次尝试结束后（含失败尝试）立即**写 AsyncVATTasks.NotifyRequest/NotifyResponse/NotifyStatus/NotifyAttempts/NotifyTime（`save_api_task_result` / `fail_api_task` 传入落库回调；NotifyStatus 受表 CHECK 约束仅允许 skipped/success/failed，无"发送中"中间态，首次失败尝试即写入 `failed` + 当次错误）。注意重试链总耗时上限 ≈ 4×10 秒 + 3×5 秒 = 55 秒，RPA【执行Python代码】步骤的超时需允许该时长，否则进程会被中途杀掉（落库信息保留到被杀前最后一次尝试）。

**依赖**: pymssql

## 依赖说明

### 核心依赖（必需）

- **PyMuPDF** (>=1.23.0) - PDF处理

### 可选依赖

- **Pillow** (>=10.0.0) - 图像处理（仅qrcode*.py需要）
- **opencv-python** (>=4.8.0) - 图像处理（仅qrcode*.py需要）
- **numpy** (>=1.24.0) - 数值计算（仅qrcode*.py需要）
- **pyzbar** (>=0.1.9) - 二维码识别（仅qrcode*.py需要）
- **pymssql** - SQL Server 连接（仅 rpa_030_*.py 需要）

### 最小化安装

如果不需要二维码功能，只需安装：

```bash
pip install PyMuPDF
```

## 常见问题

### Q: PyMuPDF安装失败？
A: 尝试升级pip或使用国内镜像
```bash
pip install --upgrade pip
pip install PyMuPDF -i https://pypi.tuna.tsinghua.edu.cn/simple
```

### Q: pyzbar导入错误？
A: 需要安装系统级的zbar库
- Windows: http://zbar.sourceforge.net/
- macOS: `brew install zbar`
- Linux: `sudo apt-get install libzbar0`

### Q: 如何在虚拟环境中使用？
A:
```bash
python -m venv venv
source venv/bin/activate  # Linux/macOS
venv\Scripts\activate     # Windows
pip install -r requirements.txt
```

## 使用示例

### 示例1: 标准化PDF
```bash
python normalize_pdf.py original.pdf normalized.pdf
```

### 示例2: 删除PDF第4页
```bash
python remove_pdf_page.py input.pdf output.pdf 4
```

### 示例3: 提取Word模板占位符
```bash
python extract_placeholders.py template.docx
```

### 示例4: 检测企业信用报告
```bash
python credit_report_detector.py report.pdf
```

## 相关文档

- [PyMuPDF文档](https://pymupdf.readthedocs.io/)

## 技术支持

如果遇到问题，请检查：
1. Python版本是否>=3.8
2. 依赖包是否正确安装
3. 系统库（如zbar）是否安装

## 总结

大多数脚本只需要 **PyMuPDF** 一个依赖包，安装非常简单：

```bash
pip install PyMuPDF
```

只有二维码功能需要额外的图像处理库。
