WordPress Updater – DarkCorners

Date: 17/12/2025

Category: Python

  • Phần mềm hỗ trợ cập nhật lại bài viết wordpress hàng loạt.
  • Hỗ trợ cập nhật lại điểm SEO hàng loạt khi dùng Yoast SEO.
  • Sử dụng chromedrive.exe để làm trình duyệt.
  1. Khởi động phần mềm.
  2. Chọn tệp chứa danh sách liên kết cần truy cập. Các liên kết theo đúng dạng : https://yoursite.com/wp-admin/post.php?post=xxxx (với xxxx là id bài viết wordpress).
  3. Chọn thời gian ngẫu nhiên đợi giữa các lần cập nhật.
  4. Bạn có muốn ẩn trình duyệt hay không?
  5. Bạn có muốn lưu các liên kết bị lỗi ra tệp error hay không?
  6. Nhấn nút [Bắt Đầu Mở Trình Duyệt].
  7. Phần mềm sẽ khởi động chromedrive.exe . Tiếp theo bạn cần đăng nhập tài khoản quản trị thủ công.
  8. Sau khi đăng nhập xong. Nhấn nút [Đã Đăng Nhập Xong].
  9. Phần mềm sẽ bắt đầu quá trình thực hiện.
  10. Theo dõi lịch trình xử lý.
import os
import threading
import time
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import traceback

def center_window(root, width=800, height=600):
    # 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 WPUpdaterApp:
    def __init__(self, root):
        self.root = root
        self.root.title("WordPress Updater - DarkCorners")
        center_window(self.root, 800, 600)
        self.links = []
        self.driver = None
        self.is_paused = False
        self.processing_thread = None
        self.total_links = 0
        self.pending_links = 0
        self.updated_links = 0
        self.error_links = 0
        self.ready_to_process = False
        self.build_ui()

    def build_ui(self):
        # Hàng 1 : Tiêu đề phần mềm
        title_label = tk.Label(self.root, text="WordPress Updater - DarkCorners", font=('Arial', 14, 'bold'))
        title_label.pack(pady=(10, 0))

        # Hàng 2 Bên Trái : Chọn file danh sách liên kết
        top_frame = tk.Frame(self.root)
        top_frame.pack(pady=5, fill='x', padx=10)
        config_frame = tk.LabelFrame(top_frame, text="Danh Sách Liên Kết", font=('Arial', 10, 'bold'), width=500, height=80)
        config_frame.pack(side=tk.LEFT, padx=5, pady=5)
        config_frame.pack_propagate(False)
        file_row = tk.Frame(config_frame)
        file_row.pack(fill='x', padx=5, pady=2)
        self.file_path_entry = tk.Entry(file_row)
        self.file_path_entry.pack(side=tk.LEFT, fill='x', expand=True)
        tk.Button(file_row, text="📂 Chọn", command=self.load_links).pack(side=tk.LEFT, padx=5)
        warning_label = tk.Label(config_frame, text="Chọn tệp txt chứa danh sách liên kết! Mỗi liên kết một dòng!", fg='red', font=('Arial', 9, 'bold'))
        warning_label.pack(anchor='w', padx=5, pady=(0,5))
        # Hàng 2 Bên Phải : Tính năng tùy chỉnh
        option_frame = tk.LabelFrame(top_frame, text="Tính Năng Tùy Chỉnh", font=('Arial', 10, 'bold'), width=300, height=80)
        option_frame.pack(side=tk.LEFT, padx=5, pady=5)
        option_frame.pack_propagate(False)
        delay_frame = tk.Frame(option_frame)
        delay_frame.pack(anchor='w', padx=5, pady=2)
        tk.Label(delay_frame, text="⏱ Thời Gian Chờ Giãn Cách (giây):").pack(side=tk.LEFT)
        self.delay_var = tk.IntVar(value=3)
        tk.Entry(delay_frame, textvariable=self.delay_var, width=5).pack(side=tk.LEFT, padx=5)
        check_frame = tk.Frame(option_frame)
        check_frame.pack(anchor='w', padx=5, pady=2)
        self.headless_var = tk.BooleanVar()
        tk.Checkbutton(check_frame, text="Ẩn Cửa Sổ Chrome", variable=self.headless_var).pack(side=tk.LEFT)
        self.save_errors_var = tk.BooleanVar()
        tk.Checkbutton(check_frame, text="Lưu Lỗi Ra File", variable=self.save_errors_var).pack(side=tk.LEFT)

        # Hàng 3 : Các nút điều khiển
        controls_frame = tk.Frame(self.root)
        controls_frame.pack(pady=5)
        self.start_button = tk.Button(controls_frame, text="▶️ Bắt Đầu Mở Trình Duyệt", command=self.open_browser)
        self.start_button.pack(side=tk.LEFT, padx=5)
        self.continue_button = tk.Button(controls_frame, text="✅ Đã Đăng Nhập Xong", command=self.start_processing, state='disabled')
        self.continue_button.pack(side=tk.LEFT, padx=5)
        self.pause_button = tk.Button(controls_frame, text="⏸️ Tạm Dừng", command=self.pause_processing, state='disabled')
        self.pause_button.pack(side=tk.LEFT, padx=5)
        self.resume_button = tk.Button(controls_frame, text="⏩ Tiếp Tục", command=self.resume_processing, state='disabled')
        self.resume_button.pack(side=tk.LEFT, padx=5)
        self.exit_button = tk.Button(controls_frame, text="❌ Thoát", command=self.root.quit)
        self.exit_button.pack(side=tk.LEFT, padx=5)

        # Hàng 4: Log, tiến trình và hướng dẫn
        middle_frame = tk.Frame(self.root)
        middle_frame.pack(fill='both', expand=True, padx=10, pady=5)
        # Hàng 4 Bên Trái : Lịch trình xử lý
        log_frame = tk.LabelFrame(middle_frame, text="Lịch Trình Xử Lý", font=('Arial', 10, 'bold'), width=500)
        log_frame.pack(side=tk.LEFT, fill='both', padx=5, pady=5)
        log_frame.pack_propagate(False)
        self.log_text = tk.Text(log_frame)
        self.log_text.pack(fill='both', expand=True)
        right_area = tk.Frame(middle_frame, width=300, height=400)
        right_area.pack(side=tk.LEFT, fill='both', expand=True, padx=5, pady=5)
        right_area.pack_propagate(False)
        # Hàng 4 Bên Phải 1 : Tiến trình xử lý
        progress_area = tk.LabelFrame(right_area, text="Tiến Trình Xử Lý", font=('Arial', 10, 'bold'), width=300, height=150)
        progress_area.pack(side=tk.TOP, fill='x', pady=(0, 10))
        progress_area.pack_propagate(False)
        self.progress_var = tk.DoubleVar()
        self.progress = ttk.Progressbar(progress_area, maximum=100, variable=self.progress_var)
        self.progress.pack(fill='x', padx=5, pady=5)
        self.label_total = tk.Label(progress_area, text="Tổng Số Liên Kết: 0", font=('Arial', 9, 'bold'), fg='red')
        self.label_total.pack(anchor='w', padx=5)
        self.label_updated = tk.Label(progress_area, text="Đã Cập Nhật: 0", font=('Arial', 9, 'bold'), fg='green')
        self.label_updated.pack(anchor='w', padx=5)
        self.label_pending = tk.Label(progress_area, text="Đợi Cập Nhật: 0", font=('Arial', 9, 'bold'), fg='blue')
        self.label_pending.pack(anchor='w', padx=5)
        self.label_errors = tk.Label(progress_area, text="Lỗi Cập Nhật: 0", font=('Arial', 9, 'bold'), fg='black')
        self.label_errors.pack(anchor='w', padx=5)
        # Hàng 4 Bên Phải 2 : Hướng dẫn
        guide_frame = tk.LabelFrame(right_area, text="Hướng Dẫn Khởi Chạy", font=('Arial', 10, 'bold'), height=180)
        guide_frame.pack(side=tk.TOP, fill='both', expand=True, pady=(10, 0))
        guide_frame.pack_propagate(False)
        guide_text = tk.Text(guide_frame, wrap='word', font=('Arial', 9), height=8)
        guide_text.insert(tk.END, 
          "1. Chọn tệp txt chứa danh sách liên kết.\n\n"
          "2. Nhấn nút Bắt Đầu Mở Trình Duyệt.\n\n"
          "3. Phần mềm sẽ mở trình duyệt Chrome. Bạn cần truy cập vào Dashboard WordPress thủ công.\n\n"
          "4. Sau khi đăng nhập tài khoản xong. Nhấn nút Đã Đăng Nhập Xong.\n\n"
          "5. Phần mềm sẽ bắt đầu quá trình cập nhật các liên kết wordpress trong danh sách !\n\n"
        )
        guide_text.config(state='disabled')
        guide_text.pack(fill='both', expand=True, padx=5, pady=5)

    def log(self, message):
        self.log_text.insert(tk.END, f"{message}\n")
        self.log_text.see(tk.END)

    def update_status(self):
        self.label_total.config(text=f"Tổng Số Liên Kế: {self.total_links}")
        self.label_pending.config(text=f"Đợi Cập Nhật: {self.pending_links}")
        self.label_updated.config(text=f"Đã Cập Nhật: {self.updated_links}")
        self.label_errors.config(text=f"Lỗi Cập Nhật: {self.error_links}")
        if self.total_links:
            self.progress_var.set((self.updated_links + self.error_links) / self.total_links * 100)

    def load_links(self):
        file_path = filedialog.askopenfilename(filetypes=[("Text Files", "*.txt")])
        if not file_path:
            return
        self.file_path_entry.delete(0, tk.END)
        self.file_path_entry.insert(0, file_path)
        with open(file_path, 'r', encoding='utf-8') as f:
            self.links = [line.strip() for line in f if line.strip()]
        self.total_links = len(self.links)
        self.pending_links = len(self.links)
        self.updated_links = 0
        self.error_links = 0
        self.update_status()
        self.log(f"📄 Đã tìm thấy {self.total_links} liên kết từ file bạn chọn.")

    def create_driver(self, headless=False):
        options = Options()
        if headless:
            options.add_argument("--headless=new")
            options.add_argument("--disable-gpu")
            options.add_argument("--no-sandbox")
            options.add_argument("--disable-dev-shm-usage")
        service = Service("chromedriver.exe")
        return webdriver.Chrome(service=service, options=options)

    def open_browser(self):
        self.log("🧱 Đang mở trình duyệt để bạn đăng nhập vào WordPress...")
        headless = self.headless_var.get()
        try:
            self.driver = self.create_driver(headless=headless)
            self.driver.get("https://example.com/wp-admin")
        except Exception as e:
            tb = traceback.format_exc()
            self.log(f"❌ Không thể khởi tạo trình duyệt:\n{tb}")
            messagebox.showerror("Lỗi", f"Không thể mở trình duyệt:\n{e}")
            return
        self.start_button['state'] = 'disabled'
        self.continue_button['state'] = 'normal'

    def start_processing(self):
        self.log("🚀 Bắt đầu xử lý các liên kết sau khi đăng nhập wordpress.")
        self.is_paused = False
        self.total_links = len(self.links)
        self.pending_links = len(self.links)
        self.updated_links = 0
        self.error_links = 0
        self.update_status()
        self.continue_button['state'] = 'disabled'
        self.pause_button['state'] = 'normal'
        self.resume_button['state'] = 'normal'
        self.processing_thread = threading.Thread(target=self.process_links)
        self.processing_thread.start()

    def pause_processing(self):
        self.is_paused = True
        self.log("⏸️ Đã tạm dừng.")

    def resume_processing(self):
        self.is_paused = False
        self.log("▶️ Tiếp tục xử lý các liên kết.")
        self.processing_thread = threading.Thread(target=self.process_links)
        self.processing_thread.start()

    def process_links(self):
        error_links = []
        while self.links:
            if self.is_paused:
                time.sleep(1)
                continue
            link = self.links.pop(0)
            self.log(f"🌐 Đang mở: {link}")
            try:
                self.driver.get(link)
                WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "body")))
                time.sleep(self.delay_var.get())
                update_button = WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.ID, "publish")))
                update_button.click()
                self.updated_links += 1
                self.log("✅ Đã cập nhật thành công liên kết vừa mở.")
            except Exception as e:
                self.error_links += 1
                self.log(f"❌ Lỗi: {str(e)}")
                error_links.append(link)
            self.pending_links = len(self.links)
            self.update_status()
        if self.driver:
            self.driver.quit()
        self.log("🎉 Đã hoàn tất cập nhật tất cả liên kết trong tệp danh sách liên kết.")
        if self.save_errors_var.get() and error_links:
            with open("links_error.txt", "w", encoding="utf-8") as f:
                f.write("\n".join(error_links))
            self.log("📅 Đã lưu các liên kết lỗi vào links_error.txt.")

if __name__ == "__main__":
    root = tk.Tk()
    app = WPUpdaterApp(root)
    root.mainloop()
pyinstaller --noconsole --onefile --windowed --add-data "chromedriver.exe;." --add-data "5-WordpressUpdater-icon.ico;." --icon=5-WordpressUpdater-icon.ico 5-WordPressUpdater-Source.py

Để lại một bình luận