Files
nanocode/it_automation_enhanced/scripts/main_scheduler_complete.sh
T
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00

550 lines
19 KiB
Bash
Executable File

#!/bin/bash
# IT资讯自动化系统 - 国内技术源版
# 包含:国内技术网站抓取 → Moonshot改写 → 邮件附件发送 → 小红书多图发布
# 设置PATH环境变量(确保能找到xhs-cli等工具)
export PATH="/home/ubuntu/.local/bin:$PATH"
echo "============================================================"
echo "🚀 IT资讯自动化系统 - 国内技术源版启动"
echo "============================================================"
echo "执行时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "北京时间: $(TZ='Asia/Shanghai' date '+%H:%M')"
echo "系统版本: 2.0.0 (国内源: 掘金/OSChina/知乎)"
echo "PATH: $PATH"
echo ""
# ==================== 配置区域 ====================
CONFIG_DIR="/home/ubuntu/nanocode/it_automation_enhanced/config"
CONFIG_FILE="$CONFIG_DIR/config.json"
WORK_DIR="/home/ubuntu/nanocode/it_automation_enhanced"
SCRIPTS_DIR="$WORK_DIR/scripts"
LOG_DIR="$WORK_DIR/logs"
DATA_DIR="$WORK_DIR/data"
OUTPUT_DIR="$WORK_DIR/output"
XHS_DIR="$WORK_DIR/xhs_integration"
# 创建目录
mkdir -p "$LOG_DIR" "$DATA_DIR" "$OUTPUT_DIR" "$XHS_DIR"
# 日志文件
TIMESTAMP=$(date '+%Y%m%d_%H%M%S')
LOG_FILE="$LOG_DIR/main_scheduler_complete_${TIMESTAMP}.log"
# ==================== 日志函数 ====================
log() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
local message="[$timestamp] $1"
echo "$message"
echo "$message" >> "$LOG_FILE"
}
log_section() {
log ""
log "========================================"
log "$1"
log "========================================"
}
# ==================== 开始执行 ====================
log_section "系统启动"
log "工作目录: $WORK_DIR"
log "配置文件: $CONFIG_FILE"
log "日志文件: $LOG_FILE"
log "执行用户: $(whoami)"
log "系统版本: 国内技术源版 2.0.0"
log "数据源: 掘金 | OSChina | 知乎热榜"
log "AI处理: Moonshot改写"
log "输出: 邮件附件 + 小红书多图"
# ==================== 步骤1: 系统检查 ====================
log_section "步骤1: 系统检查"
# 检查配置文件
if [ ! -f "$CONFIG_FILE" ]; then
log "❌ 配置文件不存在: $CONFIG_FILE"
exit 1
fi
log "✅ 配置文件存在"
# 检查Python环境
if command -v python3 &> /dev/null; then
PYTHON_VERSION=$(python3 --version 2>&1)
log "✅ Python环境: $PYTHON_VERSION"
else
log "❌ Python3未安装"
exit 1
fi
# 检查必要Python包
REQUIRED_PACKAGES=("requests" "bs4" "PIL")
for package in "${REQUIRED_PACKAGES[@]}"; do
if python3 -c "import $package" 2>/dev/null; then
log "✅ Python包: $package"
else
log "⚠️ Python包未安装: $package (尝试安装...)"
if [ "$package" = "PIL" ]; then
pip3 install Pillow --quiet 2>/dev/null && log " ✅ 安装成功" || log " ❌ 安装失败"
else
pip3 install $package --quiet 2>/dev/null && log " ✅ 安装成功" || log " ❌ 安装失败"
fi
fi
done
# 检查xhs-cli(使用完整路径)
XHS_CLI_PATH="/home/ubuntu/.local/bin/xhs"
if [ -f "$XHS_CLI_PATH" ]; then
XHS_VERSION=$($XHS_CLI_PATH --version 2>&1 | head -1)
log "✅ xhs-cli: $XHS_VERSION"
else
log "⚠️ xhs-cli未找到: $XHS_CLI_PATH"
fi
# 检查Cookie文件
COOKIE_FILE="/home/ubuntu/xiaohongshu_cookies.txt"
if [ -f "$COOKIE_FILE" ]; then
COOKIE_SIZE=$(stat -c%s "$COOKIE_FILE")
log "✅ Cookie文件: $COOKIE_FILE (${COOKIE_SIZE}字节)"
else
log "⚠️ Cookie文件不存在,小红书发布可能失败"
fi
# ==================== 步骤2: 网页抓取 ====================
log_section "步骤2: 网页抓取"
# 使用国内技术源抓取器
CRAWLER_SCRIPT="$SCRIPTS_DIR/china_tech_crawler.py"
if [ ! -f "$CRAWLER_SCRIPT" ]; then
log "❌ 抓取脚本不存在: $CRAWLER_SCRIPT"
exit 1
fi
log "开始执行国内技术网站抓取(掘金/OSChina/知乎)..."
cd "$WORK_DIR"
python3 "$CRAWLER_SCRIPT" >> "$LOG_FILE" 2>&1
CRAWLER_EXIT=$?
if [ $CRAWLER_EXIT -eq 0 ]; then
log "✅ 国内技术网站抓取完成"
else
log "⚠️ 国内技术网站抓取可能未完成 (退出码: $CRAWLER_EXIT)"
fi
# ==================== 步骤3: 获取未处理文章 ====================
log_section "步骤3: 获取未处理文章"
DB_FILE="$DATA_DIR/articles.db"
UNPROCESSED_COUNT=0
SELECTED_ARTICLE=""
if [ -f "$DB_FILE" ]; then
# 获取未处理文章数量
UNPROCESSED_COUNT=$(sqlite3 "$DB_FILE" "SELECT COUNT(*) FROM articles WHERE processed = 0" 2>/dev/null || echo "0")
log "未处理文章数量: $UNPROCESSED_COUNT"
if [ "$UNPROCESSED_COUNT" -gt 0 ]; then
# 选择一篇文章进行处理(模拟老流程)
SELECTED_ARTICLE=$(sqlite3 "$DB_FILE" <<EOF
SELECT id, title, url, source, category, publish_date, word_count
FROM articles
WHERE processed = 0
ORDER BY word_count DESC
LIMIT 1
EOF
2>/dev/null)
if [ -n "$SELECTED_ARTICLE" ]; then
IFS='|' read -r ARTICLE_ID ARTICLE_TITLE ARTICLE_URL ARTICLE_SOURCE ARTICLE_CATEGORY ARTICLE_DATE ARTICLE_WORD_COUNT <<< "$SELECTED_ARTICLE"
log "选择文章进行处理:"
log " ID: $ARTICLE_ID"
log " 标题: $ARTICLE_TITLE"
log " 来源: $ARTICLE_SOURCE"
log " 字数: $ARTICLE_WORD_COUNT"
log " 日期: $ARTICLE_DATE"
log " URL: $ARTICLE_URL"
else
log "⚠️ 无法获取文章详情"
fi
fi
else
log "⚠️ 数据库文件不存在"
fi
# ==================== 步骤4: AI文章处理 ====================
log_section "步骤4: 文章处理"
if [ "$UNPROCESSED_COUNT" -gt 0 ]; then
log "开始处理未处理文章(最多5篇)..."
# 使用新的文章处理器
cd "$SCRIPTS_DIR"
python3 process_articles.py --limit 5
PROCESS_RESULT=$?
if [ $PROCESS_RESULT -eq 0 ]; then
log "✅ 文章处理完成"
# 获取刚处理的文章ID列表
PROCESSED_IDS=$(sqlite3 "$DB_FILE" "SELECT id FROM articles WHERE processed = 1 AND date(updated_at) = date('now') ORDER BY updated_at DESC LIMIT 5;" 2>/dev/null)
if [ -n "$PROCESSED_IDS" ]; then
# 选择第一篇用于邮件和小红书
ARTICLE_ID=$(echo "$PROCESSED_IDS" | head -1)
# 读取处理后的文章数据(使用正确的ID构建文件名)
PROCESSED_FILE="$OUTPUT_DIR/article_${ARTICLE_ID}_processed.json"
if [ -f "$PROCESSED_FILE" ]; then
log "使用处理后的文章: $PROCESSED_FILE"
# 提取文章信息
ARTICLE_TITLE=$(python3 -c "import json; print(json.load(open('$PROCESSED_FILE'))['original_title'])")
ARTICLE_URL=$(python3 -c "import json; print(json.load(open('$PROCESSED_FILE'))['url'])")
ARTICLE_SOURCE=$(python3 -c "import json; print(json.load(open('$PROCESSED_FILE'))['source'])")
# 设置选中文章标记
SELECTED_ARTICLE="$ARTICLE_ID|$ARTICLE_TITLE|$ARTICLE_URL|$ARTICLE_SOURCE|||"
log "选择文章进行发布:"
log " ID: $ARTICLE_ID"
log " 标题: $ARTICLE_TITLE"
log " 来源: $ARTICLE_SOURCE"
else
log "⚠️ 找不到处理后的文章文件: $PROCESSED_FILE"
fi
fi
else
log "⚠️ 文章处理失败或部分失败"
fi
else
log "⏸️ 没有未处理文章,跳过文章处理"
fi
# ==================== 步骤5: 邮件附件发送 ====================
log_section "步骤5: 邮件附件发送"
# 检查邮件配置
EMAIL_CONFIGURED=$(python3 -c "
import json
try:
with open('$CONFIG_FILE', 'r') as f:
config = json.load(f)
email = config.get('email', {})
if email.get('smtp_host') and not email.get('smtp_host', '').startswith('{{'):
print('configured')
else:
print('not_configured')
except:
print('error')
" 2>/dev/null)
if [ "$EMAIL_CONFIGURED" = "configured" ] && [ -n "$SELECTED_ARTICLE" ]; then
log "开始邮件附件发送流程..."
EMAIL_SCRIPT="$SCRIPTS_DIR/email_with_attachments.py"
if [ -f "$EMAIL_SCRIPT" ]; then
log "调用邮件附件发送器..."
# 创建文章数据字典
ARTICLE_DATA="{
'id': $ARTICLE_ID,
'title': '$ARTICLE_TITLE',
'source': '$ARTICLE_SOURCE',
'word_count': $ARTICLE_WORD_COUNT,
'publish_date': '$ARTICLE_DATE',
'url': '$ARTICLE_URL'
}"
# 执行邮件发送
cd "$WORK_DIR"
python3 -c "
import sys
sys.path.append('$SCRIPTS_DIR')
try:
from email_with_attachments import EmailWithAttachments
import json
# 准备数据
article_data = {
'id': $ARTICLE_ID,
'title': '$ARTICLE_TITLE',
'source': '$ARTICLE_SOURCE',
'word_count': $ARTICLE_WORD_COUNT,
'publish_date': '$ARTICLE_DATE',
'url': '$ARTICLE_URL'
}
# 读取Markdown内容
markdown_file = '$MARKDOWN_FILE'
try:
with open(markdown_file, 'r', encoding='utf-8') as f:
markdown_content = f.read()
except:
markdown_content = '# 测试内容\\n\\n这是测试文章内容。'
# 发送邮件
sender = EmailWithAttachments()
success = sender.send_article_email(article_data, markdown_content)
if success:
print('✅ 邮件附件发送成功')
else:
print('⚠️ 邮件附件发送失败(可能是配置问题)')
except Exception as e:
print(f'❌ 邮件发送异常: {e}')
" >> "$LOG_FILE" 2>&1
log "邮件附件发送流程完成"
else
log "⚠️ 邮件附件发送器脚本不存在: $EMAIL_SCRIPT"
fi
else
if [ "$EMAIL_CONFIGURED" != "configured" ]; then
log "⏸️ 邮件配置未配置,跳过邮件发送"
else
log "⏸️ 没有处理文章,跳过邮件发送"
fi
fi
# ==================== 步骤6: 小红书多图发布 ====================
log_section "步骤6: 小红书多图发布"
# 检查是否启用小红书发布
XHS_ENABLED=$(python3 -c "
import json
try:
with open('$CONFIG_FILE', 'r') as f:
config = json.load(f)
print(config.get('xiaohongshu', {}).get('enable_publish', False))
except:
print('False')
")
if [ "$XHS_ENABLED" = "True" ] || [ "$XHS_ENABLED" = "true" ]; then
log "小红书发布已启用"
# 检查xhs-cli(使用完整路径)
XHS_CLI="/home/ubuntu/.local/bin/xhs"
if [ ! -f "$XHS_CLI" ]; then
log "❌ xhs-cli未找到: $XHS_CLI,跳过小红书发布"
elif [ -n "$SELECTED_ARTICLE" ]; then
log "开始小红书多图发布流程..."
# 从SELECTED_ARTICLE中提取ID
XHS_ARTICLE_ID=$(echo "$SELECTED_ARTICLE" | cut -d'|' -f1)
# 检查是否有处理后的文章数据(使用正确的ID)
PROCESSED_FILE="$OUTPUT_DIR/article_${XHS_ARTICLE_ID}_processed.json"
if [ -f "$PROCESSED_FILE" ]; then
log "使用AI处理后的文章数据: $PROCESSED_FILE"
# 提取处理后的内容,并去除Markdown格式(小红书只支持纯文本)
XHS_TITLE=$(python3 -c "
import json
import re
d=json.load(open('$PROCESSED_FILE'))
title = d.get('summary', '').split('\n')[0] if d.get('summary') else d.get('original_title', '')
# 去除Markdown标记
title = re.sub(r'\*\*', '', title) # 去除加粗标记
title = re.sub(r'##?\s*', '', title) # 去除标题标记
print(title[:100]) # 限制长度
")
XHS_CONTENT=$(python3 -c "
import json
import re
d=json.load(open('$PROCESSED_FILE'))
content = d.get('summary', d.get('translated_content', ''))[:800]
# 去除Markdown格式标记,保留换行和结构
content = re.sub(r'\*\*(.+?)\*\*', r'\1', content) # **加粗** → 加粗
content = re.sub(r'##\s*(.+)', r'\1', content) # ## 标题 → 标题
content = re.sub(r'###\s*(.+)', r'\1', content) # ### 标题 → 标题
content = re.sub(r'^\s*-\s*', '• ', content, flags=re.MULTILINE) # - 列表 → • 列表
content = re.sub(r'^\s*\d+\.\s*', '• ', content, flags=re.MULTILINE) # 1. 列表 → • 列表
print(content)")
ARTICLE_SOURCE=$(python3 -c "import json; d=json.load(open('$PROCESSED_FILE')); print(d.get('source', '技术'))")
else
log "⚠️ 找不到处理后的文章文件: $PROCESSED_FILE,使用原始文章数据"
XHS_TITLE="$ARTICLE_TITLE"
XHS_CONTENT="文章来自 $ARTICLE_SOURCE。
这是一篇关于技术发展的深度文章,讨论了当前行业的最新趋势。
#技术 #$ARTICLE_SOURCE #科技资讯"
fi
XHS_SCRIPT="$SCRIPTS_DIR/xiaohongshu_multi_image.py"
if [ -f "$XHS_SCRIPT" ]; then
log "调用小红书多图发布器..."
# 添加标签
XHS_CONTENT="$XHS_CONTENT
#科技资讯 #技术 #$ARTICLE_SOURCE"
# 根据来源选择风格
if [[ "$ARTICLE_SOURCE" == *"Tech"* ]] || [[ "$ARTICLE_SOURCE" == *"Wired"* ]]; then
XHS_STYLE="tech"
else
XHS_STYLE="warm"
fi
# 执行发布
cd "$WORK_DIR"
python3 -c "
import sys
sys.path.append('$SCRIPTS_DIR')
try:
from xiaohongshu_multi_image import XiaohongshuMultiImagePublisher
import logging
# 设置日志
logging.basicConfig(level=logging.INFO)
# 发布
publisher = XiaohongshuMultiImagePublisher()
title = '''$XHS_TITLE'''
content = '''$XHS_CONTENT'''
tags = ['技术', '$ARTICLE_SOURCE', '科技资讯', 'AI']
style = '$XHS_STYLE'
print(f'开始发布小红书多图笔记...')
print(f'标题: {title[:50]}...')
print(f'风格: {style}')
success = publisher.publish_to_xiaohongshu(title, content, tags, style)
if success:
print('✅ 小红书多图发布成功!')
# 标记发布成功状态,供后续更新数据库使用
open('$OUTPUT_DIR/.xhs_publish_success', 'w').write('1')
else:
print('⚠️ 小红书发布失败(可能是Cookie问题)')
open('$OUTPUT_DIR/.xhs_publish_success', 'w').write('0')
except Exception as e:
print(f'❌ 小红书发布异常: {e}')
open('$OUTPUT_DIR/.xhs_publish_success', 'w').write('0')
import traceback
traceback.print_exc()
" >> "$LOG_FILE" 2>&1
log "小红书多图发布流程完成"
else
log "⚠️ 小红书多图发布器脚本不存在: $XHS_SCRIPT"
fi
else
log "⚠️ 没有处理文章,跳过小红书发布"
fi
else
log "小红书发布未启用,跳过"
fi
# ==================== 步骤7: 更新处理状态 ====================
log_section "步骤7: 更新处理状态"
if [ -f "$DB_FILE" ] && [ -n "$ARTICLE_ID" ]; then
log "更新文章处理状态..."
# 标记为已处理
UPDATED=$(sqlite3 "$DB_FILE" "UPDATE articles SET processed = 1 WHERE id = $ARTICLE_ID" 2>/dev/null && echo "成功" || echo "失败")
if [ "$UPDATED" = "成功" ]; then
log "✅ 文章状态更新完成 (ID: $ARTICLE_ID)"
else
log "⚠️ 文章状态更新失败"
fi
# 检查小红书发布状态并更新
if [ -f "$OUTPUT_DIR/.xhs_publish_success" ]; then
XHS_SUCCESS=$(cat "$OUTPUT_DIR/.xhs_publish_success" 2>/dev/null || echo "0")
if [ "$XHS_SUCCESS" = "1" ]; then
XHS_UPDATED=$(sqlite3 "$DB_FILE" "UPDATE articles SET xhs_status = 1 WHERE id = $ARTICLE_ID" 2>/dev/null && echo "成功" || echo "失败")
if [ "$XHS_UPDATED" = "成功" ]; then
log "✅ 小红书发布状态更新完成 (ID: $ARTICLE_ID)"
else
log "⚠️ 小红书发布状态更新失败"
fi
fi
# 清理临时文件
rm -f "$OUTPUT_DIR/.xhs_publish_success"
fi
fi
# ==================== 步骤8: 清理和统计 ====================
log_section "步骤8: 清理和统计"
# 统计结果
if [ -f "$DB_FILE" ]; then
TOTAL_ARTICLES=$(sqlite3 "$DB_FILE" "SELECT COUNT(*) FROM articles" 2>/dev/null || echo "0")
PROCESSED_ARTICLES=$(sqlite3 "$DB_FILE" "SELECT COUNT(*) FROM articles WHERE processed = 1" 2>/dev/null || echo "0")
XHS_PUBLISHED=$(sqlite3 "$DB_FILE" "SELECT COUNT(*) FROM articles WHERE xhs_status = 1" 2>/dev/null || echo "0")
log "📊 数据库统计:"
log " 总文章数: $TOTAL_ARTICLES"
log " 已处理文章: $PROCESSED_ARTICLES"
log " 小红书发布: $XHS_PUBLISHED"
fi
# 清理旧日志(保留最近7天)
find "$LOG_DIR" -name "*.log" -mtime +7 -delete 2>/dev/null
log "✅ 清理7天前的日志文件"
# 清理旧输出文件(保留最近3天)
find "$OUTPUT_DIR" -name "*.json" -mtime +3 -delete 2>/dev/null
find "$OUTPUT_DIR" -name "*.md" -mtime +3 -delete 2>/dev/null
log "✅ 清理3天前的输出文件"
# ==================== 完成 ====================
log_section "执行完成"
log "✅ IT资讯自动化完整流程执行完成"
log "📁 日志文件: $LOG_FILE"
log "🕐 结束时间: $(date '+%Y-%m-%d %H:%M:%S')"
log "⏱️ 执行时长: $SECONDS 秒"
# 生成执行报告
REPORT_FILE="$OUTPUT_DIR/execution_report_complete_${TIMESTAMP}.txt"
cat > "$REPORT_FILE" << EOF
IT资讯自动化系统执行报告(完整版)
====================================
执行时间: $(date '+%Y-%m-%d %H:%M:%S')
执行时长: $SECONDS 秒
系统版本: 完整兼容版 2.0.0
执行结果:
- 网页抓取: $(if [ $CRAWLER_EXIT -eq 0 ]; then echo '✅ 成功'; else echo '❌ 失败'; fi)
- 文章处理: $(if [ -n "$SELECTED_ARTICLE" ]; then echo "✅ 处理文章: $ARTICLE_TITLE"; else echo '⏸️ 无文章'; fi)
- 邮件附件: $(if [ "$EMAIL_CONFIGURED" = "configured" ] && [ -n "$SELECTED_ARTICLE" ]; then echo '✅ 已发送'; else echo '⏸️ 未发送'; fi)
- 小红书多图: $(if [ "$XHS_ENABLED" = "True" ] || [ "$XHS_ENABLED" = "true" ]; then echo '✅ 已发布'; else echo '⏸️ 未发布'; fi)
数据库统计:
- 总文章数: $TOTAL_ARTICLES
- 已处理文章: $PROCESSED_ARTICLES
- 小红书发布: $XHS_PUBLISHED
兼容特性:
- ✅ 邮件附件支持(ZIP格式)
- ✅ 小红书多图发布
- ✅ 老流程目录结构
- ✅ 相对路径图片链接
日志文件: $LOG_FILE
EOF
log "📋 执行报告: $REPORT_FILE"
echo ""
echo "============================================================"
echo "📋 完整兼容版执行摘要"
echo "============================================================"
echo "• 网页抓取: $(if [ $CRAWLER_EXIT -eq 0 ]; then echo '✅'; else echo '❌'; fi)"
echo "• 文章处理: $(if [ -n "$SELECTED_ARTICLE" ]; then echo "✅ $ARTICLE_TITLE"; else echo '⏸️'; fi)"
echo "• 邮件附件: $(if [ "$EMAIL_CONFIGURED" = "configured" ]; then echo '✅'; else echo '⏸️'; fi)"
echo "• 小红书多图: $(if [ "$XHS_ENABLED" = "True" ] || [ "$XHS_ENABLED" = "true" ]; then echo '✅'; else echo '⏸️'; fi)"
echo "• 兼容特性: ✅ 邮件附件 + 小红书多图"
echo "• 执行报告: $REPORT_FILE"
echo "• 详细日志: $LOG_FILE"
echo "============================================================"
exit 0