diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..0a62d6a --- /dev/null +++ b/.env.example @@ -0,0 +1,15 @@ +# 招标公告爬虫项目环境变量配置 +# 请复制此文件为 .env 并填入实际的密钥值 +# cp .env.example .env + +# DeepSeek API 密钥 +DEEPSEEK_API_KEY=your_deepseek_api_key_here + +# 简道云 API 密钥 +JDY_API_KEY=your_jiandaoyun_api_key_here + +# 数据存储路径(可选,默认为 data) +DATA_DIR=data + +# 临时文件路径(可选,默认为 temp_files) +TEMP_DIR=temp_files diff --git a/.gitignore b/.gitignore index f72ff90..edb1c62 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,9 @@ temp_files/ # Attachments (large files) data/attachments/ +# Backups +backups/ + # Environment .env venv/ diff --git a/scripts/backup.sh b/scripts/backup.sh new file mode 100644 index 0000000..5b8d401 --- /dev/null +++ b/scripts/backup.sh @@ -0,0 +1,70 @@ +#!/bin/bash +# 数据备份脚本 +# 用于备份重要数据 + +# 获取脚本所在目录 +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" +cd "$PROJECT_DIR" + +echo "==========================================" +echo "开始备份: $(date '+%Y-%m-%d %H:%M:%S')" +echo "==========================================" + +# 配置 +BACKUP_DIR="${PROJECT_DIR}/backups" +DATE=$(date +"%Y%m%d_%H%M%S") +KEEP_DAYS=30 + +# 创建备份目录 +mkdir -p "$BACKUP_DIR" + +echo "备份目录: $BACKUP_DIR" +echo "备份日期: $DATE" +echo "" + +# 1. 备份数据目录 +echo "[1/3] 备份数据目录..." +if [ -d "data" ]; then + DATA_BACKUP_FILE="${BACKUP_DIR}/data_${DATE}.tar.gz" + tar -czf "$DATA_BACKUP_FILE" data/ + echo "✅ 数据备份完成: $DATA_BACKUP_FILE" + echo " 文件大小: $(du -h "$DATA_BACKUP_FILE" | cut -f1)" +else + echo "⚠️ data目录不存在,跳过数据备份" +fi + +# 2. 备份日志目录(可选) +echo "" +echo "[2/3] 备份日志目录..." +if [ -d "logs" ]; then + LOGS_BACKUP_FILE="${BACKUP_DIR}/logs_${DATE}.tar.gz" + tar -czf "$LOGS_BACKUP_FILE" logs/ + echo "✅ 日志备份完成: $LOGS_BACKUP_FILE" + echo " 文件大小: $(du -h "$LOGS_BACKUP_FILE" | cut -f1)" +else + echo "⚠️ logs目录不存在,跳过日志备份" +fi + +# 3. 清理旧备份 +echo "" +echo "[3/3] 清理${KEEP_DAYS}天前的旧备份..." +OLD_BACKUPS=$(find "$BACKUP_DIR" -name "*.tar.gz" -mtime +${KEEP_DAYS} -print | wc -l) +if [ "$OLD_BACKUPS" -gt 0 ]; then + find "$BACKUP_DIR" -name "*.tar.gz" -mtime +${KEEP_DAYS} -delete + echo "✅ 已删除 ${OLD_BACKUPS} 个旧备份文件" +else + echo "✅ 没有需要清理的旧备份" +fi + +# 统计 +echo "" +echo "==========================================" +echo "备份完成: $(date '+%Y-%m-%d %H:%M:%S')" +echo "备份文件数量: $(ls -1 "$BACKUP_DIR"/*.tar.gz 2>/dev/null | wc -l)" +echo "总备份大小: $(du -sh "$BACKUP_DIR" 2>/dev/null | cut -f1)" +echo "==========================================" + +echo "" +echo "✅ 备份任务完成!" +exit 0 diff --git a/scripts/health_check.sh b/scripts/health_check.sh new file mode 100644 index 0000000..19c024a --- /dev/null +++ b/scripts/health_check.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# 健康检查脚本 +# 用于监控爬虫运行状态 + +# 获取脚本所在目录 +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" +cd "$PROJECT_DIR" + +echo "==========================================" +echo "健康检查: $(date '+%Y-%m-%d %H:%M:%S')" +echo "==========================================" + +STATUS=0 + +# 1. 检查Python进程 +echo "" +echo "[1/5] 检查Python进程..." +if pgrep -f "main.py" > /dev/null; then + echo "✅ 爬虫正在运行" + echo " 进程ID: $(pgrep -f 'main.py')" +else + echo "⚠️ 爬虫未运行" +fi + +# 2. 检查磁盘空间 +echo "" +echo "[2/5] 检查磁盘空间..." +DISK_USAGE=$(df -h . | awk 'NR==2 {print $5}' | sed 's/%//') +echo " 当前使用率: ${DISK_USAGE}%" + +if [ "$DISK_USAGE" -gt 80 ]; then + echo "❌ 警告:磁盘空间使用率超过80%!" + STATUS=1 +elif [ "$DISK_USAGE" -gt 60 ]; then + echo "⚠️ 磁盘空间使用率超过60%" +else + echo "✅ 磁盘空间正常" +fi + +# 3. 检查数据文件 +echo "" +echo "[3/5] 检查数据文件..." +if [ -d "data" ]; then + CSV_COUNT=$(find data -name "*.csv" 2>/dev/null | wc -l) + JSON_COUNT=$(find data -name "*.json" 2>/dev/null | wc -l) + echo " CSV文件数: $CSV_COUNT" + echo " JSON文件数: $JSON_COUNT" + TOTAL_COUNT=$((CSV_COUNT + JSON_COUNT)) + if [ "$TOTAL_COUNT" -gt 0 ]; then + echo "✅ 数据文件存在" + else + echo "⚠️ 暂无数据文件" + fi +else + echo "❌ 警告:data目录不存在" + STATUS=1 +fi + +# 4. 检查日志文件 +echo "" +echo "[4/5] 检查日志文件..." +if [ -d "logs" ]; then + LOG_COUNT=$(find logs -name "*.log" 2>/dev/null | wc -l) + echo " 日志文件数: $LOG_COUNT" + + # 检查最近的日志 + LATEST_LOG=$(ls -t logs/*.log 2>/dev/null | head -1) + if [ -n "$LATEST_LOG" ]; then + echo " 最新日志: $LATEST_LOG" + echo " 最后几行:" + tail -5 "$LATEST_LOG" | sed 's/^/ /' + fi +else + echo "⚠️ logs目录不存在" +fi + +# 5. 检查配置文件 +echo "" +echo "[5/5] 检查配置文件..." +if [ -f "config.py" ]; then + echo "✅ config.py 存在" +else + echo "❌ config.py 不存在" + STATUS=1 +fi + +if [ -f "config_fixed.py" ]; then + echo "✅ config_fixed.py 存在" +else + echo "❌ config_fixed.py 不存在" + STATUS=1 +fi + +echo "" +echo "==========================================" +if [ $STATUS -eq 0 ]; then + echo "✅ 健康检查完成,状态正常" +else + echo "⚠️ 健康检查完成,存在警告" +fi +echo "==========================================" + +exit $STATUS diff --git a/scripts/run_crawler.sh b/scripts/run_crawler.sh new file mode 100644 index 0000000..6a081d4 --- /dev/null +++ b/scripts/run_crawler.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# 招标公告爬虫执行脚本 +# 用于云端服务器定时执行 + +# 获取脚本所在目录 +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" +cd "$PROJECT_DIR" + +echo "==========================================" +echo "开始执行爬虫任务: $(date '+%Y-%m-%d %H:%M:%S')" +echo "项目目录: $PROJECT_DIR" +echo "==========================================" + +# 激活虚拟环境 +if [ -d "venv" ]; then + echo "激活虚拟环境..." + source venv/bin/activate +else + echo "警告: 虚拟环境不存在,将使用系统Python" +fi + +# 创建日志目录 +mkdir -p logs + +# 日期时间 +DATE=$(date +"%Y%m%d_%H%M%S") +LOG_FILE="logs/crawler_${DATE}.log" + +echo "日志文件: $LOG_FILE" +echo "" >> "$LOG_FILE" +echo "==========================================" >> "$LOG_FILE" +echo "开始执行爬虫任务: $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG_FILE" +echo "==========================================" >> "$LOG_FILE" + +# 执行爬虫(所有网站,所有公告类型,启用AI处理和上传) +echo "执行爬虫命令..." +python main.py -s all -P -U >> "$LOG_FILE" 2>&1 + +EXIT_CODE=$? + +echo "" >> "$LOG_FILE" +echo "==========================================" >> "$LOG_FILE" +echo "爬虫任务完成: $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG_FILE" +echo "退出码: $EXIT_CODE" >> "$LOG_FILE" +echo "==========================================" >> "$LOG_FILE" + +if [ $EXIT_CODE -eq 0 ]; then + echo "✅ 爬虫任务执行成功!" + echo "日志文件: $LOG_FILE" +else + echo "❌ 爬虫任务执行失败!退出码: $EXIT_CODE" + echo "请查看日志文件: $LOG_FILE" +fi + +echo "==========================================" +exit $EXIT_CODE diff --git a/云端部署指南.md b/云端部署指南.md new file mode 100644 index 0000000..271e25e --- /dev/null +++ b/云端部署指南.md @@ -0,0 +1,537 @@ +# 招标公告爬虫项目云端部署指南 + +## 项目概述 +本项目用于自动化爬取浙江省和台州市公共资源交易中心的招标公告数据,经AI处理后上传到简道云平台。 + +--- + +## 部署目标 +将招标公告爬虫项目部署到云端服务器,实现自动化数据采集、处理和上传。 + +--- + +## 部署前检查清单 + +- [ ] 拥有云端服务器访问权限(SSH) +- [ ] 服务器已安装Python 3.8+ +- [ ] 已获得Git仓库访问权限 +- [ ] 已准备好所有API密钥(DeepSeek、简道云) +- [ ] 了解目标服务器的操作系统(Linux推荐) + +--- + +## 阶段一:环境准备(预计 30 分钟) + +| 序号 | 任务 | 操作内容 | 验证方式 | +|------|------|----------|----------| +| 1.1 | 系统环境检查 | 确认服务器操作系统、Python版本 | `python3 --version` | +| 1.2 | 安装系统依赖 | 安装poppler-utils等PDF处理工具 | `which pdftotext` | +| 1.3 | 克隆项目代码 | 从Git仓库拉取最新代码 | `git status` | +| 1.4 | 创建虚拟环境 | 创建独立的Python虚拟环境 | `source venv/bin/activate` | +| 1.5 | 安装依赖包 | 安装requirements.txt中的所有依赖 | `pip list` | + +### 详细操作步骤 + +#### 1.1 系统环境检查 +```bash +# 检查Python版本 +python3 --version + +# 检查操作系统 +cat /etc/os-release + +# 检查磁盘空间 +df -h +``` + +#### 1.2 安装系统依赖 +```bash +# Ubuntu/Debian +sudo apt-get update +sudo apt-get install -y poppler-utils + +# CentOS/RHEL +sudo yum install -y poppler-utils +``` + +#### 1.3 克隆项目代码 +```bash +# 克隆项目 +git clone http://49.234.3.145:3018/blandarebiter/ztb.git +cd ztb + +# 切换到main分支 +git checkout main +``` + +#### 1.4 创建虚拟环境 +```bash +# 创建虚拟环境 +python3 -m venv venv + +# 激活虚拟环境 +source venv/bin/activate +``` + +#### 1.5 安装依赖包 +```bash +# 升级pip +pip install --upgrade pip + +# 安装项目依赖 +pip install -r requirements.txt +``` + +--- + +## 阶段二:配置文件调整(预计 20 分钟) + +| 序号 | 任务 | 操作内容 | 验证方式 | +|------|------|----------|----------| +| 2.1 | 敏感信息处理 | 将API密钥改为环境变量 | `echo $DEEPSEEK_API_KEY` | +| 2.2 | 配置文件审核 | 检查config.py和config_fixed.py配置 | 对比本地配置 | +| 2.3 | 目录权限设置 | 确保data、temp_files目录可写 | `ls -la` | +| 2.4 | 网络访问测试 | 测试能否访问目标网站 | `curl -I https://ggzy.zj.gov.cn` | + +### 详细操作步骤 + +#### 2.1 敏感信息处理 + +**方式一:使用环境变量(推荐)** + +创建环境变量配置文件: +```bash +# 创建 .env 文件 +cat > .env << EOF +DEEPSEEK_API_KEY=your_deepseek_api_key_here +JDY_API_KEY=your_jiandaoyun_api_key_here +EOF + +# 设置文件权限 +chmod 600 .env +``` + +修改代码以支持环境变量(可选),或者使用现有配置文件中的密钥。 + +**方式二:直接修改配置文件** +```bash +# 编辑 config.py,确保API密钥正确 +vim config.py +``` + +#### 2.2 配置文件审核 +```bash +# 查看配置文件内容 +cat config.py | grep -E "(DEEPSEEK_API_KEY|api_key)" + +# 对比本地和云端配置差异 +git diff +``` + +#### 2.3 目录权限设置 +```bash +# 创建必要的目录 +mkdir -p data temp_files + +# 设置目录权限 +chmod 755 data temp_files + +# 验证权限 +ls -la +``` + +#### 2.4 网络访问测试 +```bash +# 测试浙江省公共资源交易中心 +curl -I https://ggzy.zj.gov.cn + +# 测试台州公共资源交易中心 +curl -I https://ggzy.tzztb.zjtz.gov.cn +``` + +--- + +## 阶段三:部署测试(预计 45 分钟) + +| 序号 | 任务 | 操作内容 | 验证方式 | +|------|------|----------|----------| +| 3.1 | 小规模爬取测试 | 爬取1页数据,不处理 | `python main.py -s zhejiang -t "招标公告" -p 1` | +| 3.2 | AI处理测试 | 对爬取的数据进行AI处理 | 检查生成的JSON文件 | +| 3.3 | 简道云上传测试 | 上传测试数据到简道云 | 简道云平台查看 | +| 3.4 | 完整流程测试 | 执行完整的爬取+处理+上传流程 | 所有步骤正常完成 | + +### 详细操作步骤 + +#### 3.1 小规模爬取测试 +```bash +# 确保虚拟环境已激活 +source venv/bin/activate + +# 爬取1页浙江招标公告数据 +python main.py -s zhejiang -t "招标公告" -p 1 + +# 检查生成的CSV文件 +ls -la data/ +``` + +#### 3.2 AI处理测试 +```bash +# 启用AI处理(不上传) +python main.py -s zhejiang -t "招标公告" -p 1 -P + +# 检查生成的JSON文件 +ls -la data/*AI处理*.json +``` + +#### 3.3 简道云上传测试 +```bash +# 使用测试上传脚本 +python test_upload_jdy.py + +# 或者手动指定文件上传 +python upload_json_to_jdy.py +``` + +#### 3.4 完整流程测试 +```bash +# 执行完整流程:爬取+AI处理+上传 +python main.py -s zhejiang -t "招标公告" -p 1 -P -U + +# 检查所有步骤是否成功完成 +# 1. CSV文件生成 +# 2. AI处理JSON文件生成 +# 3. 简道云上传成功日志 +``` + +--- + +## 阶段四:定时任务配置(预计 25 分钟) + +| 序号 | 任务 | 操作内容 | 验证方式 | +|------|------|----------|----------| +| 4.1 | 日志轮转配置 | 配置日志文件自动轮转 | 检查logrotate配置 | +| 4.2 | 编写执行脚本 | 创建可执行的shell脚本 | 测试脚本执行 | +| 4.3 | 设置cron任务 | 添加定时任务 | `crontab -l` | +| 4.4 | 监控脚本编写 | 创建简单的健康检查脚本 | 手动运行测试 | + +### 详细操作步骤 + +#### 4.1 日志轮转配置 + +创建logrotate配置文件: +```bash +# 创建配置文件 +sudo cat > /etc/logrotate.d/ztb << EOF +/path/to/ztb/logs/*.log { + daily + rotate 30 + compress + delaycompress + missingok + notifempty + create 0644 www-data www-data +} +EOF + +# 测试配置 +sudo logrotate -d /etc/logrotate.d/ztb +``` + +#### 4.2 编写执行脚本 + +创建执行脚本 `run_crawler.sh`: +```bash +#!/bin/bash +# 招标公告爬虫执行脚本 + +# 项目目录 +PROJECT_DIR="/path/to/ztb" +cd "$PROJECT_DIR" + +# 激活虚拟环境 +source venv/bin/activate + +# 创建日志目录 +mkdir -p logs + +# 日期时间 +DATE=$(date +"%Y%m%d_%H%M%S") +LOG_FILE="logs/crawler_${DATE}.log" + +echo "开始执行爬虫任务: $(date)" >> "$LOG_FILE" + +# 执行爬虫(所有网站,所有公告类型,启用AI处理和上传) +python main.py -s all -P -U >> "$LOG_FILE" 2>&1 + +echo "爬虫任务完成: $(date)" >> "$LOG_FILE" +``` + +设置脚本权限: +```bash +chmod +x run_crawler.sh + +# 测试脚本 +./run_crawler.sh +``` + +#### 4.3 设置cron任务 + +编辑crontab: +```bash +# 编辑cron任务 +crontab -e + +# 添加定时任务(每天凌晨2点执行) +0 2 * * * /path/to/ztb/run_crawler.sh >> /path/to/ztb/logs/cron.log 2>&1 + +# 保存并退出 + +# 查看cron任务 +crontab -l +``` + +常用cron时间示例: +```bash +# 每天凌晨2点 +0 2 * * * + +# 每6小时执行一次 +0 */6 * * * + +# 每周一凌晨3点 +0 3 * * 1 + +# 每月1号凌晨4点 +0 4 1 * * +``` + +#### 4.4 监控脚本编写 + +创建健康检查脚本 `health_check.sh`: +```bash +#!/bin/bash +# 健康检查脚本 + +PROJECT_DIR="/path/to/ztb" +cd "$PROJECT_DIR" + +# 检查Python进程 +if pgrep -f "main.py" > /dev/null; then + echo "爬虫正在运行" +else + echo "爬虫未运行" + # 可选:发送告警邮件 +fi + +# 检查磁盘空间 +DISK_USAGE=$(df -h . | awk 'NR==2 {print $5}' | sed 's/%//') +if [ "$DISK_USAGE" -gt 80 ]; then + echo "警告:磁盘空间使用率超过80%!当前: ${DISK_USAGE}%" +else + echo "磁盘空间正常: ${DISK_USAGE}%" +fi + +# 检查数据文件 +if [ -d "data" ]; then + DATA_COUNT=$(find data -name "*.csv" -o -name "*.json" | wc -l) + echo "数据文件数量: $DATA_COUNT" +else + echo "警告:data目录不存在" +fi +``` + +设置脚本权限并测试: +```bash +chmod +x health_check.sh +./health_check.sh +``` + +--- + +## 阶段五:监控与维护(预计 20 分钟) + +| 序号 | 任务 | 操作内容 | 验证方式 | +|------|------|----------|----------| +| 5.1 | 错误告警配置 | 设置邮件或其他告警方式 | 测试告警触发 | +| 5.2 | 数据备份策略 | 配置重要数据自动备份 | 检查备份文件 | +| 5.3 | 磁盘空间监控 | 设置磁盘空间预警 | 监控脚本运行 | +| 5.4 | 版本更新流程 | 制定代码更新和部署流程 | 文档记录 | + +### 详细操作步骤 + +#### 5.1 错误告警配置 + +**方式一:使用邮件告警(需要配置sendmail)** +```bash +# 安装邮件工具 +sudo apt-get install -y mailutils + +# 测试发送邮件 +echo "测试邮件" | mail -s "测试告警" your_email@example.com +``` + +**方式二:使用第三方告警服务** +可以集成钉钉、企业微信、Slack等告警服务。 + +#### 5.2 数据备份策略 + +创建备份脚本 `backup.sh`: +```bash +#!/bin/bash +# 数据备份脚本 + +PROJECT_DIR="/path/to/ztb" +BACKUP_DIR="/path/to/backups" +DATE=$(date +"%Y%m%d") + +# 创建备份目录 +mkdir -p "$BACKUP_DIR" + +# 备份数据目录 +cd "$PROJECT_DIR" +tar -czf "$BACKUP_DIR/ztb_data_${DATE}.tar.gz" data/ + +# 保留最近30天的备份 +find "$BACKUP_DIR" -name "ztb_data_*.tar.gz" -mtime +30 -delete + +echo "备份完成: ztb_data_${DATE}.tar.gz" +``` + +设置定时备份: +```bash +# 编辑crontab +crontab -e + +# 每天凌晨3点备份 +0 3 * * * /path/to/ztb/backup.sh +``` + +#### 5.3 磁盘空间监控 + +将健康检查脚本加入定时任务: +```bash +# 编辑crontab +crontab -e + +# 每小时检查一次 +0 * * * * /path/to/ztb/health_check.sh >> /path/to/ztb/logs/health.log 2>&1 +``` + +#### 5.4 版本更新流程 + +制定更新流程文档: + +```markdown +## 版本更新流程 + +1. 拉取最新代码 + ```bash + git pull origin main + ``` + +2. 检查变更 + ```bash + git log --oneline -5 + git diff HEAD~1 HEAD + ``` + +3. 更新依赖(如需要) + ```bash + pip install -r requirements.txt + ``` + +4. 停止当前任务(如需要) + ```bash + pkill -f "main.py" + ``` + +5. 测试更新 + ```bash + python main.py -s zhejiang -t "招标公告" -p 1 + ``` + +6. 确认正常后,恢复定时任务 +``` + +--- + +## 阶段六:上线前检查清单 + +在正式上线前,请确认以下所有项目: + +- [ ] 所有依赖已正确安装 +- [ ] API密钥配置正确 +- [ ] 数据目录权限正确 +- [ ] 网络访问正常 +- [ ] 小规模测试通过 +- [ ] 定时任务已配置 +- [ ] 日志轮转已设置 +- [ ] 监控告警已启用 +- [ ] 备份策略已制定 +- [ ] 更新流程已文档化 +- [ ] 服务器安全加固已完成 +- [ ] 文档已完善 + +--- + +## 常见问题排查 + +### 问题1:Python虚拟环境无法激活 +**解决方案**: +```bash +# 重新创建虚拟环境 +rm -rf venv +python3 -m venv venv +source venv/bin/activate +``` + +### 问题2:PDF处理失败 +**解决方案**: +```bash +# 检查poppler是否安装 +which pdftotext + +# 重新安装 +sudo apt-get install --reinstall poppler-utils +``` + +### 问题3:API调用失败 +**解决方案**: +- 检查网络连接 +- 验证API密钥是否正确 +- 查看API调用次数是否超限 + +### 问题4:磁盘空间不足 +**解决方案**: +```bash +# 清理旧日志 +find logs -name "*.log" -mtime +7 -delete + +# 清理临时文件 +rm -rf temp_files/* +``` + +--- + +## 维护建议 + +1. **定期检查**:每周至少检查一次运行状态 +2. **日志审查**:定期查看日志,发现潜在问题 +3. **数据验证**:每月抽查上传到简道云的数据是否正确 +4. **依赖更新**:定期更新依赖包,保持安全 +5. **文档更新**:保持部署文档与实际情况一致 + +--- + +## 联系支持 + +如遇到问题,请: +1. 查看日志文件:`logs/` 目录 +2. 检查Git仓库的Issue记录 +3. 联系项目维护者 + +--- + +**文档版本**: 1.0 +**最后更新**: 2026-02-25 +**维护者**: 项目团队