144 lines
6.2 KiB
Python
144 lines
6.2 KiB
Python
import logging
|
|
import uiautomator2 as u2
|
|
import time
|
|
import re
|
|
|
|
class ShopeeBot:
|
|
def __init__(self, device_ip: str):
|
|
logging.info(f"Đang kết nối tới thiết bị {device_ip}...")
|
|
self.d = u2.connect(device_ip)
|
|
logging.info("Kết nối thành công!")
|
|
|
|
def get_commission_rate(self, url: str) -> str:
|
|
try:
|
|
# 1. Đảm bảo màn hình sáng
|
|
self.d.screen_on()
|
|
|
|
# 2. Khởi động lại Shopee từ đầu để tránh lỗi luồng cũ
|
|
logging.info("Khởi động Shopee...")
|
|
self.d.app_start("com.shopee.vn", stop=True)
|
|
time.sleep(6) # Chờ app khởi động hoàn toàn
|
|
|
|
# Tắt popup quảng cáo nếu có (nhấn phím Back hoặc tìm nút Tắt)
|
|
# Dùng thử phím Back 1 lần nếu có popup che màn hình
|
|
self.d.press("back")
|
|
time.sleep(1)
|
|
|
|
# 3. Chuyển sang tab "Tôi"
|
|
logging.info("Vào tab Tôi...")
|
|
if self.d(text="Tôi").exists:
|
|
self.d(text="Tôi").click()
|
|
else:
|
|
return "Lỗi: Không tìm thấy tab 'Tôi'"
|
|
time.sleep(2)
|
|
|
|
# 4. Tìm và ấn "Shopee Tiếp Thị Liên Kết"
|
|
logging.info("Tìm mục Shopee Tiếp Thị Liên Kết...")
|
|
# Cuộn xuống cho đến khi thấy chữ này
|
|
self.d(scrollable=True).scroll.to(textContains="Tiếp Thị Liên Kết")
|
|
|
|
if self.d(textContains="Tiếp Thị Liên Kết").exists:
|
|
self.d(textContains="Tiếp Thị Liên Kết").click()
|
|
else:
|
|
return "Lỗi: Không tìm thấy mục Tiếp Thị Liên Kết"
|
|
|
|
time.sleep(6) # Mục này có thể tải hơi lâu vì gọi API
|
|
|
|
# 5. Ấn tab "Tài khoản" ở thanh menu dưới cùng của Affiliate
|
|
logging.info("Vào tab Tài khoản...")
|
|
if self.d(text="Tài khoản").exists:
|
|
self.d(text="Tài khoản").click()
|
|
else:
|
|
return "Lỗi: Không tìm thấy tab Tài khoản"
|
|
time.sleep(2)
|
|
|
|
# 5.1. Bấm vào "Chuyển đổi liên kết" trong danh sách
|
|
logging.info("Bấm vào mục Chuyển đổi liên kết...")
|
|
if self.d(text="Chuyển đổi liên kết").exists:
|
|
self.d(text="Chuyển đổi liên kết").click()
|
|
else:
|
|
return "Lỗi: Không tìm thấy mục Chuyển đổi liên kết"
|
|
time.sleep(2)
|
|
|
|
# 6. Nhập link vào ô Text
|
|
logging.info("Nhập link sản phẩm...")
|
|
# Nếu có nút "Xóa tất cả" link cũ thì xóa trước
|
|
if self.d(text="Xóa tất cả").exists:
|
|
self.d(text="Xóa tất cả").click()
|
|
time.sleep(0.5)
|
|
|
|
# Tìm ô nhập liệu (thường là EditText)
|
|
edit_text = self.d(className="android.widget.EditText")
|
|
if edit_text.exists:
|
|
edit_text.set_text(url)
|
|
else:
|
|
return "Lỗi: Không tìm thấy ô nhập link"
|
|
time.sleep(1)
|
|
|
|
# 7. Bấm nút Chuyển Đổi màu cam
|
|
logging.info("Bấm nút Chuyển Đổi...")
|
|
if self.d(text="Chuyển Đổi").exists:
|
|
self.d(text="Chuyển Đổi").click()
|
|
else:
|
|
return "Lỗi: Không tìm thấy nút Chuyển Đổi"
|
|
|
|
time.sleep(4) # Chờ Shopee convert link và hiện kết quả
|
|
|
|
# 8. Lấy tỷ lệ hoa hồng, link mới và giá
|
|
logging.info("Đang đọc kết quả trên màn hình...")
|
|
|
|
import json
|
|
import re
|
|
|
|
result_data = {
|
|
"status": "success",
|
|
"commission": "",
|
|
"affiliate_link": "",
|
|
"price": "",
|
|
"message": "Trích xuất thành công"
|
|
}
|
|
|
|
# Quét toàn bộ text trên màn hình để tìm các thông tin
|
|
# Lấy tất cả các thành phần có text
|
|
all_texts = []
|
|
for elem in self.d(textMatches="(?s).*"):
|
|
t = elem.get_text()
|
|
if t and t not in all_texts:
|
|
all_texts.append(t)
|
|
|
|
for t in all_texts:
|
|
# 1. Tìm Tỷ lệ hoa hồng
|
|
if "Tỷ lệ hoa hồng" in t:
|
|
# Rút gọn lấy mỗi số (VD: "Tỷ lệ hoa hồng 10,5%" -> "10,5%")
|
|
match = re.search(r'Tỷ lệ hoa hồng\s*([\d,.]+%?)', t)
|
|
if match:
|
|
result_data["commission"] = match.group(1)
|
|
else:
|
|
result_data["commission"] = t.replace("Tỷ lệ hoa hồng", "").strip()
|
|
|
|
# 2. Tìm Affiliate Link (thường có s.shopee.vn)
|
|
if "s.shopee.vn" in t or "shp.ee" in t:
|
|
# Trích xuất phần URL, bỏ số thứ tự ví dụ "1. https://s.shopee.vn/..."
|
|
match = re.search(r'(https?://[^\s]+)', t)
|
|
if match:
|
|
result_data["affiliate_link"] = match.group(1)
|
|
|
|
# 3. Tìm Giá bán
|
|
# Thường có chữ "đ" ở đầu: đ192.000 hoặc đ90.000
|
|
if t.startswith("đ") or t.startswith("₫"):
|
|
result_data["price"] = t
|
|
|
|
if not result_data["commission"]:
|
|
# Nếu không tìm thấy, dump UI ra để debug
|
|
xml_dump = self.d.dump_hierarchy()
|
|
with open("error_dump.xml", "w", encoding="utf-8") as f:
|
|
f.write(xml_dump)
|
|
result_data["status"] = "error"
|
|
result_data["message"] = "Không thấy Tỷ lệ hoa hồng (Đã lưu error_dump.xml)"
|
|
|
|
# Trả về dạng Dictionary (FastAPI sẽ tự chuyển thành JSON cho n8n)
|
|
return result_data
|
|
|
|
except Exception as e:
|
|
return {"status": "error", "message": f"Lỗi không xác định: {str(e)}"}
|