Commit c7e972fa authored by 邱阿朋's avatar 邱阿朋

feat(price): 优化价格爬取工具并添加消息推送功能

- 将默认国家站点由“美国”改为“US”代码
- 修正输出文件命名逻辑,保证为空结果时仍创建文件
- 增加从生成的 CSV 读取价格数据并通过 RabbitMQ 推送消息
- 使用 dotenv 加载环境变量,支持配置敏感信息
- 在主程序入口添加异常捕获,优雅处理键盘中断
- README 文件大幅更新,完善项目功能说明和使用指南
- requirements.txt 添加 pyinstaller 和其他依赖,完善环境配置
parent ebfb76b7
# 亚马逊财务报表 # 亚马逊财务报表自动化处理系统
###### 已实现功能 一个用于自动化处理 Amazon Vendor Central 平台财务报表数据的 Python 应用程序。支持数据爬取、报表生成、ERP 推送等功能。
1. spa,退货,回款 爬取数据导出报表推送erp ## ✨ 功能特性
2. 退货数据推送到易仓
3. 广告费和商品销量 ### 核心功能
4. asin前台售价 - **SPA(促销协议)处理** - 自动爬取 SPA 发票数据,生成报表并推送 ERP
- **退货数据处理** - 处理退货订单,支持推送到易仓系统创建入库单
- **回款数据处理** - 处理回款数据,支持 ERP 推送
- **广告费处理** - 爬取和处理广告费用数据
- **商品销量处理** - 爬取和处理商品销售数据
- **Amazon 价格爬取** - 批量爬取商品前台售价
### 支持站点
🇺🇸 美国 (US) | 🇯🇵 日本 (JP) | 🇬🇧 英国 (UK) | 🇫🇷 法国 (FR) | 🇩🇪 德国 (DE) | 🇨🇦 加拿大 (CA) | 🇲🇽 墨西哥 (MX)
## 🚀 快速开始
### 环境要求
- Python 3.8+
- Windows 10/11(推荐)
### 安装步骤
1. **克隆项目**
```bash
git clone <repository-url>
cd amazon_reports
```
2. **创建虚拟环境**
```bash
python -m venv venv
venv\Scripts\activate # Windows
```
3. **安装依赖**
```bash
pip install -r requirements.txt
```
4. **配置环境变量**
创建 `.env` 文件,配置以下参数:
```env
# RabbitMQ 配置
RABBITMQ_HOST=47.107.31.4
RABBITMQ_PORT=5672
RABBITMQ_USER=khd_rabbitmq
RABBITMQ_PASSWORD=your_password
# Redis 配置
REDIS_HOST=47.119.182.76
REDIS_PORT=6379
REDIS_DB=12
REDIS_PASSWORD=your_password
```
## 📖 使用说明
### GUI 模式(推荐)
#### 1. 主工具 (`tool_gui.py`)
处理 SPA、退货、回款数据的主工具
```bash
python tool_gui.py
```
**使用流程:**
1. 选择国家站点
2. 选择功能(SPA查询/退货查询/ERP回款)
3. 选择是否推送消息
4. 选择输入 Excel 文件
5. 点击"开始执行"
#### 2. 广告费工具 (`super_gui.py`)
处理广告费和商品销量数据
```bash
python super_gui.py
```
**使用流程:**
1. 选择国家(支持全部或单个)
2. 选择功能(广告费/商品销量)
3. 点击"开始执行"
4. 可随时暂停/继续
#### 3. 价格爬取工具 (`price_gui.py`)
批量爬取 Amazon 商品前台售价
```bash
python price_gui.py
```
**使用流程:**
1. 选择国家站点
2. 选择包含 ASIN 列的 Excel 文件
3. 点击"开始爬取"
4. 结果保存为 CSV 文件
#### 4. 入库单创建工具 (`easy_gui.py`)
将退货数据推送到易仓系统创建入库单
```bash
python easy_gui.py
```
**使用流程:**
1. 选择仓库编码
2. 选择退货 Excel 文件
3. 点击"开始执行"
4. 结果保存为 `*_updated.xlsx`
### 命令行模式
```bash
python tool_cmd.py
```
按提示输入:
- 国家代码(DE, FR, JP, CA, UK, US)
- 店铺编码
- 功能类型(spa, return, payment, payment_erp)
- 文件名
## 📁 项目结构
```
amazon_reports/
├── app/ # 核心应用模块
│ ├── helper/ # 辅助工具(API、文件、日志等)
│ ├── logger/ # 日志模块
│ └── vc/ # Vendor Central 业务逻辑
├── easy_gui.py # 易仓入库单创建工具
├── price_gui.py # Amazon 价格爬取工具
├── super_gui.py # 广告费和商品销量工具
├── tool_gui.py # 主工具(SPA、退货、回款)
├── tool_cmd.py # 命令行工具入口
├── requirements.txt # 项目依赖
└── README.md # 项目说明
```
## 📋 输入文件格式
### SPA 处理
Excel 文件需包含发票 ID 列(Invoice ID)
### 退货处理
Excel 文件需包含以下列:
- Return ID
- Return Date
- 其他退货相关信息
### 回款处理
Excel 文件需包含回款列表数据(Payments.xlsx)
### 价格爬取
Excel 文件需包含 `ASIN`
### 入库单创建
Excel 文件需包含:
- Shipment Request ID
- SKU
- Return quantity
## 🔧 技术栈
- **GUI 框架**: ttkbootstrap
- **浏览器自动化**: DrissionPage
- **数据处理**: pandas, openpyxl, xlrd
- **消息队列**: RabbitMQ (pika)
- **缓存**: Redis
- **HTTP 请求**: requests
## ⚙️ 配置说明
### 易仓 API 配置
`easy_gui.py` 中配置易仓 API 密钥(建议移至环境变量):
```python
app_key = "your_app_key"
app_token = "your_app_token"
```
### 店铺代码映射
不同国家对应不同的店铺代码:
- US: VECELO
- JP: JP-VC
- UK: UK-VC
- DE: DE-VC
- FR: FR-VC
- CA: CA-VC
## 📝 注意事项
1. **登录要求**: 首次使用需要在浏览器中手动登录 Amazon Vendor Central 账号
2. **网络环境**: 确保能正常访问 Amazon Vendor Central 和外部 API
3. **文件路径**: 输入文件路径不要包含中文字符(建议使用英文路径)
4. **浏览器**: 程序会自动打开 Chromium 浏览器,请勿手动关闭
5. **数据备份**: 处理前请备份原始数据文件
## 🐛 常见问题
### Q: 浏览器无法打开?
A: 检查是否安装了 Chromium 浏览器,DrissionPage 会自动下载。
### Q: 登录后提示需要验证码?
A: 在浏览器中手动完成验证码验证,程序会自动继续。
### Q: 文件下载失败?
A: 检查下载目录权限,确保有写入权限。
### Q: 推送数据失败?
A: 检查 RabbitMQ 连接配置和网络连接。
## 📦 打包部署
使用 PyInstaller 打包为可执行文件:
```bash
build.bat
```
或手动打包:
```bash
pyinstaller -F -w tool_gui.py
```
## 🔒 安全提示
⚠️ **重要**: 当前版本部分敏感信息(API 密钥、密码)硬编码在代码中,建议:
1. 将所有敏感信息移至 `.env` 文件
2. 不要将 `.env` 文件提交到版本控制系统
3. 生产环境使用密钥管理服务
## 📄 许可证
[添加许可证信息]
## 👥 贡献
欢迎提交 Issue 和 Pull Request!
## 📞 联系方式
[添加联系方式]
---
**版本**: 1.0.0
**最后更新**: 2024
...@@ -4,12 +4,14 @@ import time ...@@ -4,12 +4,14 @@ import time
from typing import Tuple from typing import Tuple
import pandas as pd import pandas as pd
from DrissionPage import ChromiumPage, ChromiumOptions from DrissionPage import ChromiumPage, ChromiumOptions
from dotenv import load_dotenv
from lxml import etree from lxml import etree
import ttkbootstrap as ttk import ttkbootstrap as ttk
from ttkbootstrap.constants import * from ttkbootstrap.constants import *
from tkinter import filedialog, scrolledtext from tkinter import filedialog, scrolledtext
from threading import Thread from threading import Thread
from app.helper import rabbitmq
from app.helper.domain import switch_domain from app.helper.domain import switch_domain
class AmazonPriceScraper: class AmazonPriceScraper:
...@@ -56,8 +58,8 @@ class AmazonPriceScraper: ...@@ -56,8 +58,8 @@ class AmazonPriceScraper:
def setup_gui(self): def setup_gui(self):
ttk.Label(self.root, text="选择国家:").pack(pady=5) ttk.Label(self.root, text="选择国家:").pack(pady=5)
self.country_var = ttk.StringVar(value="美国") self.country_var = ttk.StringVar(value="US")
ttk.OptionMenu(self.root, self.country_var, "美国", *self.domains.values()).pack(pady=5) ttk.OptionMenu(self.root, self.country_var, "US", *self.domains.values()).pack(pady=5)
ttk.Button(self.root, text="选择ASIN Excel文件", command=self.load_excel).pack(pady=5) ttk.Button(self.root, text="选择ASIN Excel文件", command=self.load_excel).pack(pady=5)
self.file_label = ttk.Label(self.root, text="未选择文件") self.file_label = ttk.Label(self.root, text="未选择文件")
...@@ -147,8 +149,8 @@ class AmazonPriceScraper: ...@@ -147,8 +149,8 @@ class AmazonPriceScraper:
results.append(result) results.append(result)
self.log(f"ASIN {result[0]}: {result[1]}") self.log(f"ASIN {result[0]}: {result[1]}")
output_file = f"amazon_prices_{self.country_var.get()}_{int(time.time())}.csv"
if results: if results:
output_file = f"amazon_prices_{self.country_var.get()}_{int(time.time())}.csv"
with open(output_file, "w", encoding="utf-8", newline="") as f: with open(output_file, "w", encoding="utf-8", newline="") as f:
writer = csv.writer(f) writer = csv.writer(f)
writer.writerow(["ASIN", "Price"]) writer.writerow(["ASIN", "Price"])
...@@ -162,6 +164,26 @@ class AmazonPriceScraper: ...@@ -162,6 +164,26 @@ class AmazonPriceScraper:
self.page = None self.page = None
self.log("浏览器已关闭") self.log("浏览器已关闭")
# 读取Excel文件
data = pd.read_csv(output_file)
self.log("开始推送消息....")
client = rabbitmq.RabbitMQClient()
client.connection()
client.connect(queue='price_robot', routing_key='price_robot', exchange='product')
country = self.country_var.get()
for _, item_row in data.iterrows():
push_data = {
'currency': country,
'asin': item_row.get('ASIN', ''),
'price': item_row.get('Price', 0),
}
client.send_message(push_data)
client.close()
def start_scraping(self): def start_scraping(self):
if not self.asins: if not self.asins:
self.log("请先选择包含ASIN的Excel文件") self.log("请先选择包含ASIN的Excel文件")
...@@ -187,5 +209,9 @@ class AmazonPriceScraper: ...@@ -187,5 +209,9 @@ class AmazonPriceScraper:
self.page.quit() # 确保程序退出时关闭浏览器 self.page.quit() # 确保程序退出时关闭浏览器
if __name__ == "__main__": if __name__ == "__main__":
app = AmazonPriceScraper() try:
app.run() load_dotenv()
\ No newline at end of file app = AmazonPriceScraper()
app.run()
except KeyboardInterrupt:
exit(1)
\ No newline at end of file
...@@ -6,10 +6,12 @@ xlrd==2.0.1 ...@@ -6,10 +6,12 @@ xlrd==2.0.1
pandas==2.0.3 pandas==2.0.3
numpy==1.24.4 numpy==1.24.4
openpyxl==3.1.5 openpyxl==3.1.5
pyinstaller==6.11.0
requests==2.32.3 requests==2.32.3
redis==5.0.8 redis==5.0.8
pika==1.3.2 pika==1.3.2
python-dotenv==1.0.1 python-dotenv==1.0.1
ttkbootstrap==1.14.2 ttkbootstrap==1.14.2
xmltodict==0.14.2 xmltodict==0.14.2
\ No newline at end of file pyinstaller
setuptools==65.5.0
jaraco-text==3.11.1
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment