Compare commits
6 Commits
8bd5ffc53d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
791a19839a | ||
|
|
88ae4affa4 | ||
|
|
3dabd23dd7 | ||
|
|
7c7076f4ef | ||
|
|
a2f32dc7c4 | ||
|
|
ad1caa64b8 |
85
manage_service.sh
Normal file
85
manage_service.sh
Normal file
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# 物流服务管理脚本
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
PID_FILE="logistics_service.pid"
|
||||
LOG_FILE="logistics_service.log"
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo "启动物流服务..."
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
PID=$(cat "$PID_FILE")
|
||||
if ps -p $PID > /dev/null 2>&1; then
|
||||
echo "⚠️ 服务已在运行,PID: $PID"
|
||||
exit 1
|
||||
else
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
fi
|
||||
./run_logistics.sh --background
|
||||
;;
|
||||
stop)
|
||||
echo "停止物流服务..."
|
||||
if [ ! -f "$PID_FILE" ]; then
|
||||
echo "⚠️ PID 文件不存在,服务可能未运行"
|
||||
exit 1
|
||||
fi
|
||||
PID=$(cat "$PID_FILE")
|
||||
if ps -p $PID > /dev/null 2>&1; then
|
||||
kill $PID
|
||||
sleep 1
|
||||
if ps -p $PID > /dev/null 2>&1; then
|
||||
echo "强制停止服务..."
|
||||
kill -9 $PID
|
||||
fi
|
||||
rm -f "$PID_FILE"
|
||||
echo "✅ 服务已停止"
|
||||
else
|
||||
echo "⚠️ 进程不存在,清理 PID 文件"
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
;;
|
||||
restart)
|
||||
echo "重启物流服务..."
|
||||
$0 stop
|
||||
sleep 2
|
||||
$0 start
|
||||
;;
|
||||
status)
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
PID=$(cat "$PID_FILE")
|
||||
if ps -p $PID > /dev/null 2>&1; then
|
||||
echo "✅ 服务正在运行"
|
||||
echo "PID: $PID"
|
||||
echo "进程信息:"
|
||||
ps -p $PID -o pid,ppid,cmd,etime
|
||||
else
|
||||
echo "❌ 服务未运行(PID 文件存在但进程不存在)"
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
else
|
||||
echo "❌ 服务未运行"
|
||||
fi
|
||||
;;
|
||||
logs)
|
||||
if [ -f "$LOG_FILE" ]; then
|
||||
tail -f "$LOG_FILE"
|
||||
else
|
||||
echo "日志文件不存在: $LOG_FILE"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "用法: $0 {start|stop|restart|status|logs}"
|
||||
echo ""
|
||||
echo "命令说明:"
|
||||
echo " start - 启动服务(后台运行)"
|
||||
echo " stop - 停止服务"
|
||||
echo " restart - 重启服务"
|
||||
echo " status - 查看服务状态"
|
||||
echo " logs - 查看实时日志"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -200,6 +200,22 @@ if [ ! -d "venv" ]; then
|
||||
echo "✅ 虚拟环境创建成功"
|
||||
else
|
||||
echo "✅ 虚拟环境已存在"
|
||||
# 检查虚拟环境是否正常
|
||||
if [ -f "venv/bin/pip" ]; then
|
||||
# 检查 pip 脚本是否有行尾符问题
|
||||
if file venv/bin/pip | grep -q "CRLF"; then
|
||||
echo "⚠️ 检测到虚拟环境中的脚本有行尾符问题,正在修复..."
|
||||
find venv/bin -type f -name "pip*" -exec sed -i 's/\r$//' {} \;
|
||||
find venv/bin -type f -name "activate" -exec sed -i 's/\r$//' {} \;
|
||||
find venv/bin -type f -name "python*" -exec sed -i 's/\r$//' {} \;
|
||||
echo "✅ 行尾符已修复"
|
||||
fi
|
||||
else
|
||||
echo "⚠️ 虚拟环境可能已损坏,正在重新创建..."
|
||||
rm -rf venv
|
||||
python3 -m venv venv
|
||||
echo "✅ 虚拟环境重新创建成功"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 4. 激活虚拟环境并安装 Python 包
|
||||
@@ -207,16 +223,25 @@ echo ""
|
||||
echo "步骤 4: 安装 Python 依赖包..."
|
||||
source venv/bin/activate
|
||||
|
||||
# 验证 pip 是否可用
|
||||
if ! command -v pip >/dev/null 2>&1; then
|
||||
echo "❌ 错误: pip 命令不可用,尝试修复虚拟环境..."
|
||||
deactivate 2>/dev/null || true
|
||||
rm -rf venv
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
fi
|
||||
|
||||
# 升级 pip
|
||||
pip install --upgrade pip
|
||||
python3 -m pip install --upgrade pip
|
||||
|
||||
# 安装依赖
|
||||
pip install DrissionPage
|
||||
python3 -m pip install DrissionPage
|
||||
|
||||
# 可选:如果需要数据库功能
|
||||
read -p "是否需要数据库功能?(sqlalchemy, pymysql) [y/N]: " need_db
|
||||
if [ "$need_db" = "y" ] || [ "$need_db" = "Y" ]; then
|
||||
pip install sqlalchemy pymysql
|
||||
python3 -m pip install sqlalchemy pymysql
|
||||
fi
|
||||
|
||||
deactivate
|
||||
|
||||
417
setup_ubuntu.sh
Normal file
417
setup_ubuntu.sh
Normal file
@@ -0,0 +1,417 @@
|
||||
#!/bin/bash
|
||||
# Ubuntu 环境快速设置脚本
|
||||
|
||||
set -e # 遇到错误立即退出
|
||||
|
||||
# 确保使用 bash 运行(兼容性问题处理)
|
||||
if [ -z "$BASH_VERSION" ]; then
|
||||
echo "警告: 此脚本需要使用 bash 运行"
|
||||
echo "请使用: bash $0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=========================================="
|
||||
echo "京东物流提取工具 - Ubuntu 环境设置"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# 1. 检查并安装系统依赖
|
||||
echo "步骤 1: 检查系统依赖..."
|
||||
if ! command -v python3 >/dev/null 2>&1; then
|
||||
echo "安装 Python3..."
|
||||
sudo apt update
|
||||
sudo apt install -y python3 python3-pip python3-venv
|
||||
else
|
||||
echo "✅ Python3 已安装"
|
||||
fi
|
||||
|
||||
# 检查 Chrome/Chromium
|
||||
CHROME_PATH=""
|
||||
if command -v google-chrome >/dev/null 2>&1; then
|
||||
CHROME_PATH=$(which google-chrome)
|
||||
echo "✅ 找到 Google Chrome: $CHROME_PATH"
|
||||
elif [ -f "/usr/bin/google-chrome" ]; then
|
||||
CHROME_PATH="/usr/bin/google-chrome"
|
||||
echo "✅ 找到 Google Chrome: $CHROME_PATH"
|
||||
elif command -v chromium-browser >/dev/null 2>&1; then
|
||||
CHROME_PATH=$(which chromium-browser)
|
||||
echo "✅ 找到 Chromium: $CHROME_PATH"
|
||||
elif [ -f "/usr/bin/chromium-browser" ]; then
|
||||
CHROME_PATH="/usr/bin/chromium-browser"
|
||||
echo "✅ 找到 Chromium: $CHROME_PATH"
|
||||
else
|
||||
echo "⚠️ 未找到 Chrome/Chromium,将尝试安装..."
|
||||
echo "选择要安装的浏览器:"
|
||||
echo "1) Google Chrome (推荐)"
|
||||
echo "2) Chromium (开源版本)"
|
||||
read -p "请选择 [1-2]: " choice
|
||||
|
||||
if [ "$choice" = "1" ]; then
|
||||
echo "正在安装 Google Chrome..."
|
||||
wget -q https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||
sudo apt install -y ./google-chrome-stable_current_amd64.deb
|
||||
rm -f google-chrome-stable_current_amd64.deb
|
||||
CHROME_PATH="/usr/bin/google-chrome"
|
||||
elif [ "$choice" = "2" ]; then
|
||||
echo "正在安装 Chromium..."
|
||||
sudo apt update
|
||||
sudo apt install -y chromium-browser
|
||||
CHROME_PATH="/usr/bin/chromium-browser"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 2. 安装 Chrome 运行时依赖
|
||||
echo ""
|
||||
echo "步骤 2: 检查 Chrome 运行时依赖..."
|
||||
DEPS="libnss3 libatk-bridge2.0-0 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2"
|
||||
MISSING_DEPS=""
|
||||
|
||||
for dep in $DEPS; do
|
||||
if ! dpkg -l 2>/dev/null | grep -q "^ii.*$dep"; then
|
||||
if [ -z "$MISSING_DEPS" ]; then
|
||||
MISSING_DEPS="$dep"
|
||||
else
|
||||
MISSING_DEPS="$MISSING_DEPS $dep"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$MISSING_DEPS" ]; then
|
||||
echo "安装缺失的依赖: $MISSING_DEPS"
|
||||
sudo apt install -y $MISSING_DEPS
|
||||
else
|
||||
echo "✅ 所有依赖已安装"
|
||||
fi
|
||||
|
||||
# 3. 创建虚拟环境
|
||||
echo ""
|
||||
echo "步骤 3: 设置 Python 虚拟环境..."
|
||||
if [ ! -d "venv" ]; then
|
||||
echo "创建虚拟环境..."
|
||||
python3 -m venv venv
|
||||
echo "✅ 虚拟环境创建成功"
|
||||
else
|
||||
echo "✅ 虚拟环境已存在"
|
||||
# 检查虚拟环境是否正常
|
||||
if [ ! -f "venv/bin/pip" ]; then
|
||||
echo "⚠️ 虚拟环境可能已损坏,正在重新创建..."
|
||||
rm -rf venv
|
||||
python3 -m venv venv
|
||||
echo "✅ 虚拟环境重新创建成功"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 4. 激活虚拟环境并安装 Python 包
|
||||
echo ""
|
||||
echo "步骤 4: 安装 Python 依赖包..."
|
||||
|
||||
# 检查并修复 activate 脚本的行尾符问题
|
||||
if [ -f "venv/bin/activate" ]; then
|
||||
# 修复可能的行尾符问题
|
||||
sed -i 's/\r$//' venv/bin/activate 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 激活虚拟环境
|
||||
source venv/bin/activate
|
||||
|
||||
# 验证虚拟环境是否正常激活
|
||||
if [ -z "$VIRTUAL_ENV" ]; then
|
||||
echo "❌ 错误: 虚拟环境激活失败,尝试重新创建..."
|
||||
deactivate 2>/dev/null || true
|
||||
rm -rf venv
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
fi
|
||||
|
||||
# 升级 pip(使用 python3 -m pip 避免行尾符问题)
|
||||
echo "升级 pip..."
|
||||
python3 -m pip install --upgrade pip
|
||||
|
||||
# 安装依赖
|
||||
echo "安装 DrissionPage..."
|
||||
python3 -m pip install DrissionPage
|
||||
|
||||
# 安装 Flask(API 服务需要)
|
||||
echo "安装 Flask..."
|
||||
python3 -m pip install flask
|
||||
|
||||
# 可选:如果需要数据库功能
|
||||
read -p "是否需要数据库功能?(sqlalchemy, pymysql) [y/N]: " need_db
|
||||
if [ "$need_db" = "y" ] || [ "$need_db" = "Y" ]; then
|
||||
echo "安装数据库相关包..."
|
||||
python3 -m pip install sqlalchemy pymysql
|
||||
fi
|
||||
|
||||
deactivate
|
||||
|
||||
# 5. 创建运行脚本
|
||||
echo ""
|
||||
echo "步骤 5: 创建便捷运行脚本..."
|
||||
cat > run_logistics.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
# 激活虚拟环境并运行物流提取脚本
|
||||
|
||||
# 获取脚本所在目录
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# 检查虚拟环境是否存在
|
||||
if [ ! -d "venv" ]; then
|
||||
echo "❌ 错误: 虚拟环境不存在,请先运行 setup_ubuntu.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 修复可能的行尾符问题
|
||||
if [ -f "venv/bin/activate" ]; then
|
||||
sed -i 's/\r$//' venv/bin/activate 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 激活虚拟环境
|
||||
source venv/bin/activate
|
||||
|
||||
# 验证虚拟环境是否激活成功
|
||||
if [ -z "$VIRTUAL_ENV" ]; then
|
||||
echo "❌ 错误: 虚拟环境激活失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 使用虚拟环境中的 Python3
|
||||
PYTHON_CMD="$VIRTUAL_ENV/bin/python3"
|
||||
if [ ! -f "$PYTHON_CMD" ]; then
|
||||
PYTHON_CMD="python3"
|
||||
fi
|
||||
|
||||
# 检查脚本文件是否存在
|
||||
SCRIPT_FILE="jd/fetch_logistics_ubuntu.py"
|
||||
if [ ! -f "$SCRIPT_FILE" ]; then
|
||||
echo "❌ 错误: 找不到脚本文件 $SCRIPT_FILE"
|
||||
echo "当前目录: $(pwd)"
|
||||
echo "文件列表:"
|
||||
ls -la jd/ 2>/dev/null || echo " jd/ 目录不存在"
|
||||
echo ""
|
||||
echo "请确保脚本文件存在"
|
||||
deactivate
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查文件是否为空
|
||||
if [ ! -s "$SCRIPT_FILE" ]; then
|
||||
echo "❌ 错误: 脚本文件 $SCRIPT_FILE 为空"
|
||||
deactivate
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 修复脚本文件的行尾符问题
|
||||
sed -i 's/\r$//' "$SCRIPT_FILE" 2>/dev/null || true
|
||||
|
||||
# 检查是否要后台运行
|
||||
BACKGROUND=false
|
||||
ARGS=()
|
||||
for arg in "$@"; do
|
||||
if [ "$arg" = "--background" ] || [ "$arg" = "-b" ] || [ "$arg" = "--daemon" ] || [ "$arg" = "-d" ]; then
|
||||
BACKGROUND=true
|
||||
else
|
||||
ARGS+=("$arg")
|
||||
fi
|
||||
done
|
||||
|
||||
# 运行脚本
|
||||
echo "使用 Python: $PYTHON_CMD"
|
||||
echo "运行脚本: $SCRIPT_FILE"
|
||||
echo "脚本大小: $(wc -c < "$SCRIPT_FILE") 字节"
|
||||
|
||||
if [ "$BACKGROUND" = "true" ]; then
|
||||
# 后台运行模式
|
||||
LOG_FILE="logistics_service.log"
|
||||
PID_FILE="logistics_service.pid"
|
||||
|
||||
echo "以后台模式启动服务..."
|
||||
echo "日志文件: $LOG_FILE"
|
||||
echo "PID 文件: $PID_FILE"
|
||||
echo ""
|
||||
|
||||
# 使用 nohup 后台运行,确保使用虚拟环境的 Python
|
||||
# 注意:不传递 --background 参数给 Python 脚本
|
||||
nohup $PYTHON_CMD -u "$SCRIPT_FILE" "${ARGS[@]}" > "$LOG_FILE" 2>&1 &
|
||||
PID=$!
|
||||
echo $PID > "$PID_FILE"
|
||||
|
||||
# 等待一下,检查进程是否启动成功
|
||||
sleep 3
|
||||
if ps -p $PID > /dev/null 2>&1; then
|
||||
echo "✅ 服务已启动,PID: $PID"
|
||||
echo ""
|
||||
echo "使用以下命令管理服务:"
|
||||
echo " 查看日志: tail -f $LOG_FILE"
|
||||
echo " 停止服务: ./manage_service.sh stop"
|
||||
echo " 查看状态: ./manage_service.sh status"
|
||||
echo ""
|
||||
# 后台模式下,不退出虚拟环境(因为后台进程已经独立运行)
|
||||
# 直接退出脚本
|
||||
exit 0
|
||||
else
|
||||
echo "❌ 服务启动失败,请查看日志: $LOG_FILE"
|
||||
rm -f "$PID_FILE"
|
||||
deactivate
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# 前台运行模式
|
||||
echo "参数: ${ARGS[@]}"
|
||||
echo ""
|
||||
echo "以前台模式启动服务(按 Ctrl+C 停止)..."
|
||||
echo ""
|
||||
# 使用 -u 参数确保输出不被缓冲,并明确指定以脚本模式运行
|
||||
# 使用 exec 替换当前进程,这样 deactivate 不会执行
|
||||
exec $PYTHON_CMD -u "$SCRIPT_FILE" "${ARGS[@]}"
|
||||
# 如果 exec 失败(不应该发生),才会执行到这里
|
||||
EXIT_CODE=$?
|
||||
deactivate
|
||||
exit $EXIT_CODE
|
||||
fi
|
||||
EOF
|
||||
|
||||
chmod +x run_logistics.sh
|
||||
|
||||
# 创建服务管理脚本
|
||||
cat > manage_service.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
# 物流服务管理脚本
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
PID_FILE="logistics_service.pid"
|
||||
LOG_FILE="logistics_service.log"
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo "启动物流服务..."
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
PID=$(cat "$PID_FILE")
|
||||
if ps -p $PID > /dev/null 2>&1; then
|
||||
echo "⚠️ 服务已在运行,PID: $PID"
|
||||
exit 1
|
||||
else
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
fi
|
||||
# 重定向输出,避免显示在终端
|
||||
./run_logistics.sh --background > /dev/null 2>&1
|
||||
sleep 2
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
PID=$(cat "$PID_FILE")
|
||||
if ps -p $PID > /dev/null 2>&1; then
|
||||
echo "✅ 服务已启动,PID: $PID"
|
||||
echo "查看日志: tail -f $LOG_FILE"
|
||||
else
|
||||
echo "❌ 服务启动失败,请查看日志: $LOG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "❌ 服务启动失败,请查看日志: $LOG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
stop)
|
||||
echo "停止物流服务..."
|
||||
if [ ! -f "$PID_FILE" ]; then
|
||||
echo "⚠️ PID 文件不存在,服务可能未运行"
|
||||
exit 1
|
||||
fi
|
||||
PID=$(cat "$PID_FILE")
|
||||
if ps -p $PID > /dev/null 2>&1; then
|
||||
kill $PID
|
||||
sleep 1
|
||||
if ps -p $PID > /dev/null 2>&1; then
|
||||
echo "强制停止服务..."
|
||||
kill -9 $PID
|
||||
fi
|
||||
rm -f "$PID_FILE"
|
||||
echo "✅ 服务已停止"
|
||||
else
|
||||
echo "⚠️ 进程不存在,清理 PID 文件"
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
;;
|
||||
restart)
|
||||
echo "重启物流服务..."
|
||||
$0 stop
|
||||
sleep 2
|
||||
$0 start
|
||||
;;
|
||||
status)
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
PID=$(cat "$PID_FILE")
|
||||
if ps -p $PID > /dev/null 2>&1; then
|
||||
echo "✅ 服务正在运行"
|
||||
echo "PID: $PID"
|
||||
echo "进程信息:"
|
||||
ps -p $PID -o pid,ppid,cmd,etime
|
||||
else
|
||||
echo "❌ 服务未运行(PID 文件存在但进程不存在)"
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
else
|
||||
echo "❌ 服务未运行"
|
||||
fi
|
||||
;;
|
||||
logs)
|
||||
if [ -f "$LOG_FILE" ]; then
|
||||
tail -f "$LOG_FILE"
|
||||
else
|
||||
echo "日志文件不存在: $LOG_FILE"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "用法: $0 {start|stop|restart|status|logs}"
|
||||
echo ""
|
||||
echo "命令说明:"
|
||||
echo " start - 启动服务(后台运行)"
|
||||
echo " stop - 停止服务"
|
||||
echo " restart - 重启服务"
|
||||
echo " status - 查看服务状态"
|
||||
echo " logs - 查看实时日志"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
EOF
|
||||
|
||||
chmod +x manage_service.sh
|
||||
|
||||
# 6. 完成
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "✅ 环境设置完成!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "快速开始:"
|
||||
echo " 方式1: 使用便捷脚本(前台运行)"
|
||||
echo " ./run_logistics.sh"
|
||||
echo ""
|
||||
echo " 方式2: 后台运行服务"
|
||||
echo " ./run_logistics.sh --background"
|
||||
echo " 或"
|
||||
echo " ./run_logistics.sh -b"
|
||||
echo ""
|
||||
echo " 方式3: 手动运行"
|
||||
echo " source venv/bin/activate"
|
||||
echo " python jd/fetch_logistics_ubuntu.py"
|
||||
echo " deactivate"
|
||||
echo ""
|
||||
echo "后台运行管理:"
|
||||
echo " 方式1: 使用管理脚本(推荐)"
|
||||
echo " ./manage_service.sh start - 启动服务"
|
||||
echo " ./manage_service.sh stop - 停止服务"
|
||||
echo " ./manage_service.sh restart - 重启服务"
|
||||
echo " ./manage_service.sh status - 查看状态"
|
||||
echo " ./manage_service.sh logs - 查看日志"
|
||||
echo ""
|
||||
echo " 方式2: 直接使用 run_logistics.sh"
|
||||
echo " ./run_logistics.sh --background - 后台启动"
|
||||
echo " tail -f logistics_service.log - 查看日志"
|
||||
echo " kill \$(cat logistics_service.pid) - 停止服务"
|
||||
echo ""
|
||||
echo "浏览器路径: $CHROME_PATH"
|
||||
echo "虚拟环境: $(pwd)/venv"
|
||||
echo ""
|
||||
@@ -148,23 +148,31 @@ public class JDInnerController {
|
||||
|
||||
Comment commentToUse = null;
|
||||
|
||||
// 按优先级获取评论:
|
||||
// 按优先级获取评论,确保有图片:
|
||||
// 1️⃣ 先尝试使用未使用过的京东评论
|
||||
if (!availableComments.isEmpty()) {
|
||||
Collections.shuffle(availableComments);
|
||||
commentToUse = availableComments.get(0);
|
||||
logger.info("使用未使用过的京东评论");
|
||||
for (Comment comment : availableComments) {
|
||||
List<String> imageUrls = parsePictureUrls(comment.getPictureUrls());
|
||||
List<String> convertedImageUrls = imageConvertService.convertImageUrls(imageUrls);
|
||||
if (convertedImageUrls != null && !convertedImageUrls.isEmpty()) {
|
||||
commentToUse = comment;
|
||||
logger.info("使用未使用过的京东评论(有图片)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2️⃣ 尝试使用未使用过的淘宝评论
|
||||
else {
|
||||
if (commentToUse == null) {
|
||||
String taobaoProductIdMap = tbMap.getOrDefault(productId, null);
|
||||
if (taobaoProductIdMap != null && !taobaoProductIdMap.isEmpty()) {
|
||||
logger.info("发现淘宝映射ID,尝试获取未使用过的淘宝评论");
|
||||
Comment taobaoComment = generateTaobaoComment(productType, false);
|
||||
logger.info("发现淘宝映射ID,尝试获取未使用过的淘宝评论(有图片)");
|
||||
Comment taobaoComment = generateTaobaoCommentWithImages(productType, false);
|
||||
if (taobaoComment != null) {
|
||||
commentToUse = taobaoComment;
|
||||
isTb = true;
|
||||
logger.info("使用未使用过的淘宝评论");
|
||||
logger.info("使用未使用过的淘宝评论(有图片)");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,22 +183,29 @@ public class JDInnerController {
|
||||
List<Comment> candidateComments = new ArrayList<>();
|
||||
List<String> candidateSources = new ArrayList<>(); // 记录来源,用于标识是京东还是淘宝
|
||||
|
||||
// 添加已使用过的京东评论
|
||||
// 添加已使用过的京东评论(确保有图片)
|
||||
if (!usedComments.isEmpty()) {
|
||||
Collections.shuffle(usedComments);
|
||||
candidateComments.add(usedComments.get(0));
|
||||
candidateSources.add("JD");
|
||||
logger.info("已添加已使用过的京东评论到候选列表");
|
||||
for (Comment comment : usedComments) {
|
||||
List<String> imageUrls = parsePictureUrls(comment.getPictureUrls());
|
||||
List<String> convertedImageUrls = imageConvertService.convertImageUrls(imageUrls);
|
||||
if (convertedImageUrls != null && !convertedImageUrls.isEmpty()) {
|
||||
candidateComments.add(comment);
|
||||
candidateSources.add("JD");
|
||||
logger.info("已添加已使用过的京东评论到候选列表(有图片)");
|
||||
break; // 只添加第一个有图片的
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加已使用过的淘宝评论
|
||||
// 添加已使用过的淘宝评论(确保有图片)
|
||||
String taobaoProductIdMap = tbMap.getOrDefault(productId, null);
|
||||
if (taobaoProductIdMap != null && !taobaoProductIdMap.isEmpty()) {
|
||||
Comment taobaoComment = generateTaobaoComment(productType, true);
|
||||
Comment taobaoComment = generateTaobaoCommentWithImages(productType, true);
|
||||
if (taobaoComment != null) {
|
||||
candidateComments.add(taobaoComment);
|
||||
candidateSources.add("TB");
|
||||
logger.info("已添加已使用过的淘宝评论到候选列表");
|
||||
logger.info("已添加已使用过的淘宝评论到候选列表(有图片)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,22 +218,23 @@ public class JDInnerController {
|
||||
|
||||
if ("TB".equals(selectedSource)) {
|
||||
isTb = true;
|
||||
logger.info("随机选择:使用已使用过的淘宝评论");
|
||||
logger.info("随机选择:使用已使用过的淘宝评论(有图片)");
|
||||
} else {
|
||||
logger.info("随机选择:使用已使用过的京东评论");
|
||||
logger.info("随机选择:使用已使用过的京东评论(有图片)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (commentToUse == null) {
|
||||
return error("no comment available");
|
||||
return error("no comment with images available");
|
||||
}
|
||||
|
||||
JSONObject item = new JSONObject();
|
||||
item.put("commentText", commentToUse.getCommentText());
|
||||
// 解析图片URL并转换webp格式为jpg
|
||||
List<String> imageUrls = parsePictureUrls(commentToUse.getPictureUrls());
|
||||
List<String> convertedImageUrls = imageConvertService.convertImageUrls(imageUrls);
|
||||
|
||||
JSONObject item = new JSONObject();
|
||||
item.put("commentText", commentToUse.getCommentText());
|
||||
item.put("images", convertedImageUrls);
|
||||
|
||||
JSONArray arr = new JSONArray();
|
||||
@@ -230,12 +246,28 @@ public class JDInnerController {
|
||||
// 添加评论统计信息到响应中
|
||||
JSONObject stats = new JSONObject();
|
||||
if (!isTb) {
|
||||
// 查询最后一条京东评论的创建时间
|
||||
List<Comment> allComments = commentRepository.findByProductIdAndPictureUrlsIsNotNull(productId);
|
||||
java.time.LocalDateTime lastCommentUpdateTime = null;
|
||||
if (!allComments.isEmpty()) {
|
||||
lastCommentUpdateTime = allComments.stream()
|
||||
.map(Comment::getCreatedAt)
|
||||
.filter(createdAt -> createdAt != null)
|
||||
.max(java.time.LocalDateTime::compareTo)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
stats.put("source", "京东评论");
|
||||
stats.put("productType", productType);
|
||||
stats.put("newAdded", addCommentCount);
|
||||
stats.put("used", usedCommentCount);
|
||||
stats.put("available", canUseCommentCount);
|
||||
stats.put("total", allCommentCount);
|
||||
if (lastCommentUpdateTime != null) {
|
||||
// 转换为Date格式(前端期望的格式)
|
||||
java.util.Date updateDate = java.sql.Timestamp.valueOf(lastCommentUpdateTime);
|
||||
stats.put("lastCommentUpdateTime", updateDate.getTime());
|
||||
}
|
||||
stats.put("statisticsText",
|
||||
"京东评论统计:\n" +
|
||||
"型号 " + productType + "\n" +
|
||||
@@ -244,11 +276,27 @@ public class JDInnerController {
|
||||
"可用:" + canUseCommentCount + "\n" +
|
||||
"总数:" + allCommentCount);
|
||||
} else {
|
||||
// 查询最后一条淘宝评论的创建时间
|
||||
List<TaobaoComment> allTbComments = taobaoCommentRepository.findByProductIdAndPictureUrlsIsNotNull(taobaoProductId);
|
||||
java.time.LocalDateTime lastCommentUpdateTime = null;
|
||||
if (!allTbComments.isEmpty()) {
|
||||
lastCommentUpdateTime = allTbComments.stream()
|
||||
.map(TaobaoComment::getCreatedAt)
|
||||
.filter(createdAt -> createdAt != null)
|
||||
.max(java.time.LocalDateTime::compareTo)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
stats.put("source", "淘宝评论");
|
||||
stats.put("productType", productType);
|
||||
stats.put("used", usedTbCommentCount);
|
||||
stats.put("available", canUseTbCommentCount);
|
||||
stats.put("total", allTbCommentCount);
|
||||
if (lastCommentUpdateTime != null) {
|
||||
// 转换为Date格式(前端期望的格式)
|
||||
java.util.Date updateDate = java.sql.Timestamp.valueOf(lastCommentUpdateTime);
|
||||
stats.put("lastCommentUpdateTime", updateDate.getTime());
|
||||
}
|
||||
stats.put("statisticsText",
|
||||
"淘宝评论统计:\n" +
|
||||
"型号 " + productType + "\n" +
|
||||
@@ -279,6 +327,15 @@ public class JDInnerController {
|
||||
* @param includeUsed 是否包含已使用的评论(true=获取已使用的,false=获取未使用的)
|
||||
*/
|
||||
private Comment generateTaobaoComment(String productType, boolean includeUsed) {
|
||||
return generateTaobaoCommentWithImages(productType, includeUsed);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从淘宝评论中生成Comment对象,确保有图片
|
||||
* @param productType 商品类型
|
||||
* @param includeUsed 是否包含已使用的评论(true=获取已使用的,false=获取未使用的)
|
||||
*/
|
||||
private Comment generateTaobaoCommentWithImages(String productType, boolean includeUsed) {
|
||||
HashMap<String, String> map = jdUtil.getProductTypeMap(); // 加载京东的 productTypeMap
|
||||
HashMap<String, String> tbMap = jdUtil.getProductTypeMapForTB(); // 加载淘宝的 productTypeMapTB
|
||||
|
||||
@@ -306,31 +363,37 @@ public class JDInnerController {
|
||||
|
||||
if (!taobaoComments.isEmpty()) {
|
||||
Collections.shuffle(taobaoComments);
|
||||
TaobaoComment selected = taobaoComments.get(0);
|
||||
// 将淘宝评论转换为京东评论返回
|
||||
Comment comment = new Comment();
|
||||
comment.setCommentText(selected.getCommentText());
|
||||
String pictureUrls = selected.getPictureUrls();
|
||||
if (pictureUrls != null) {
|
||||
pictureUrls = pictureUrls.replace("//img.", "https://img.");
|
||||
}
|
||||
comment.setPictureUrls(pictureUrls);
|
||||
comment.setCommentId(selected.getCommentId());
|
||||
comment.setProductId(product_id);
|
||||
comment.setUserName(selected.getUserName());
|
||||
comment.setCreatedAt(selected.getCreatedAt());
|
||||
// 循环查找有图片的评论
|
||||
for (TaobaoComment selected : taobaoComments) {
|
||||
// 检查图片是否存在
|
||||
List<String> imageUrls = parsePictureUrls(selected.getPictureUrls());
|
||||
List<String> convertedImageUrls = imageConvertService.convertImageUrls(imageUrls);
|
||||
if (convertedImageUrls != null && !convertedImageUrls.isEmpty()) {
|
||||
// 将淘宝评论转换为京东评论返回
|
||||
Comment comment = new Comment();
|
||||
comment.setCommentText(selected.getCommentText());
|
||||
String pictureUrls = selected.getPictureUrls();
|
||||
if (pictureUrls != null) {
|
||||
pictureUrls = pictureUrls.replace("//img.", "https://img.");
|
||||
}
|
||||
comment.setPictureUrls(pictureUrls);
|
||||
comment.setCommentId(selected.getCommentId());
|
||||
comment.setProductId(product_id);
|
||||
comment.setUserName(selected.getUserName());
|
||||
comment.setCreatedAt(selected.getCreatedAt());
|
||||
|
||||
// 只在获取未使用的评论时才标记为已使用
|
||||
if (!includeUsed) {
|
||||
selected.setIsUse(1);
|
||||
taobaoCommentRepository.save(selected);
|
||||
}
|
||||
// 只在获取未使用的评论时才标记为已使用
|
||||
if (!includeUsed) {
|
||||
selected.setIsUse(1);
|
||||
taobaoCommentRepository.save(selected);
|
||||
}
|
||||
|
||||
// 返回京东评论
|
||||
return comment;
|
||||
} else {
|
||||
return null;
|
||||
// 返回京东评论
|
||||
return comment;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<String> parsePictureUrls(String raw) {
|
||||
|
||||
Reference in New Issue
Block a user