import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk
import requests
import threading
import io
def center_window(root, width=800, height=550):
# Lấy kích thước màn hình
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
# Tính vị trí bắt đầu trục ngang và trục đứng
aaaxxx = (screen_width // 2) - (width // 2)
bbbyyy = (screen_height // 2) - (height // 2) - (40)
# Đặt geometry
root.geometry(f"{width}x{height}+{aaaxxx}+{bbbyyy}")
class TikTokScraperApp:
def __init__(self, root):
self.root = root
self.root.title("Tiktok Video Scratch - DarkCorners")
self.root.resizable(False, False)
center_window(self.root, 800, 550)
self.thumbnail_image = None
self.thumbnail_data = None
# Hàng 1: Tiêu đề
title_label = tk.Label(root, text="Tiktok Video Scratch - DarkCorners", font=("Helvetica", 18, "bold"))
title_label.pack(pady=10)
# Hàng 2: Nhập URL
url_frame = tk.Frame(root)
url_frame.pack(pady=5)
tk.Label(url_frame, text="Tiktok URL:", font=("Helvetica", 12)).pack(side=tk.LEFT)
self.url_entry = tk.Entry(url_frame, width=70, font=("Helvetica", 12))
self.url_entry.pack(side=tk.LEFT, padx=10)
# Hàng 3: Mô tả + Thumbnail
content_frame = tk.Frame(root)
content_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
# Mô tả video (70%)
self.desc_text = tk.Text(content_frame, wrap=tk.WORD, font=("Helvetica", 11))
self.desc_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))
# Thumbnail (30%)
thumb_frame = tk.Frame(content_frame, width=240)
thumb_frame.pack(side=tk.RIGHT, fill=tk.Y)
self.thumb_label = tk.Label(thumb_frame)
self.thumb_label.pack(pady=5)
self.save_btn = tk.Button(thumb_frame, text="Lưu Ảnh", command=self.save_image, state=tk.DISABLED)
self.save_btn.pack(pady=5)
self.getinfo_btn = tk.Button(thumb_frame, text="Lấy Thông Tin", width=20, command=self.start_scrape)
self.getinfo_btn.pack(pady=(15, 5))
self.quit_btn = tk.Button(thumb_frame, text="Thoát", width=20, command=root.quit)
self.quit_btn.pack()
# Hàng cuối: Status
self.status_label = tk.Label(root, text="Sẵn sàng", font=("Helvetica", 10), anchor="w", relief=tk.SUNKEN)
self.status_label.pack(fill=tk.X, side=tk.BOTTOM, ipady=3)
def set_status(self, message):
self.status_label.config(text=message)
def start_scrape(self):
threading.Thread(target=self.scrape_info, daemon=True).start()
def scrape_info(self):
self.set_status("Đang xử lý...")
self.desc_text.delete(1.0, tk.END)
self.thumb_label.config(image='')
self.save_btn.config(state=tk.DISABLED)
self.thumbnail_data = None
url = self.url_entry.get().strip()
if not url:
messagebox.showwarning("Cảnh báo", "Vui lòng nhập URL TikTok.")
self.set_status("Chưa nhập URL.")
return
try:
api_url = f"https://www.tikwm.com/api/?url={url}"
response = requests.get(api_url)
data = response.json()
if data.get("code") != 0:
raise Exception("Không thể lấy thông tin video.")
video_info = data["data"]
desc = video_info.get("title", "Không có mô tả")
self.desc_text.insert(tk.END, desc)
thumb_url = video_info.get("cover")
if thumb_url:
img_response = requests.get(thumb_url)
self.thumbnail_data = img_response.content
image = Image.open(io.BytesIO(self.thumbnail_data))
image.thumbnail((200, 200))
self.thumbnail_image = ImageTk.PhotoImage(image)
self.thumb_label.config(image=self.thumbnail_image)
self.save_btn.config(state=tk.NORMAL)
self.set_status("Đã lấy ảnh thumbnail.")
else:
self.set_status("Không tìm thấy ảnh thumbnail.")
self.set_status("Lấy thông tin thành công.")
except Exception as e:
self.set_status(f"Lỗi: {str(e)}")
def save_image(self):
if not self.thumbnail_data:
return
filepath = filedialog.asksaveasfilename(
defaultextension=".jpg",
filetypes=[("JPEG files", "*.jpg"), ("All files", "*.*")],
initialfile="tiktok_thumbnail.jpg"
)
if filepath:
try:
with open(filepath, "wb") as f:
f.write(self.thumbnail_data)
self.set_status(f"Ảnh đã lưu: {filepath}")
except Exception as e:
self.set_status(f"Lỗi khi lưu ảnh: {e}")
if __name__ == "__main__":
root = tk.Tk()
app = TikTokScraperApp(root)
root.mainloop()