+1

8 Script Tự Động Hóa Bằng Python Giúp Bạn Tạm Biệt Công Việc Lặp Lại

AI đang phát triển cực kỳ nhanh chóng, và nhiều người trong chúng ta đã quen với việc ném thẳng các tác vụ vào khung chat. Tuy nhiên, AI có thể không ổn định khi xử lý các tác vụ tự động hóa, và một số dịch vụ thì không miễn phí. Đối với các tác vụ cần chạy hàng ngày, xử lý các tệp lớn hoặc giám sát trạng thái hệ thống, việc dựa vào AI có thể dẫn đến "ảo giác" (hallucinations) và kết quả không nhất quán.

AI rất tuyệt, nhưng đôi khi dùng "dao mổ trâu để giết gà" là không cần thiết. Python hoàn toàn có thể xử lý các tác vụ tự động hóa đơn giản này một cách hoàn hảo.

image.png

Trước khi viết bất kỳ dòng code Python nào, hãy đảm bảo môi trường Python của bạn đã sẵn sàng.

Tôi khuyên bạn nên sử dụng ServBay để quản lý môi trường phát triển. Nó hỗ trợ cài đặt môi trường Python chỉ với một cú nhấp chuột, bao gồm tất cả các phiên bản từ Python 2.7 cổ xưa đến Python 3.5 và thậm chí là Python 3.14 mới nhất. Tuyệt vời nhất là các phiên bản này có thể cùng tồn tại song song. Bạn không cần phải cấu hình biến môi trường thủ công hay lo lắng về việc làm rối cấu hình mặc định của hệ thống. Cài đặt xong là dùng được ngay, chỉ mất một phút.

image.png

Với một môi trường ổn định đã sẵn sàng, dưới đây là một số mẫu script tự động hóa thường được sử dụng trong công việc thực tế.

Cơ Chế Tự Động Thử Lại: Giúp Yêu Cầu Mạng Mạnh Mẽ Hơn

Biến động mạng là chuyện bình thường khi viết crawler hoặc gọi API. Thay vì viết các khối try-except ở khắp mọi nơi, hãy đóng gói logic thử lại (retry logic). Các script chuyên nghiệp sẽ không bị crash chỉ vì một lần hết thời gian chờ (timeout).

import time
import requests
from requests.exceptions import RequestException

def fetch_with_retry(url, max_retries=3, pause=2):
    """
    Yêu cầu GET với cơ chế tự động thử lại
    """
    for attempt in range(max_retries):
        try:
            # Thiết lập timeout là bắt buộc để ngăn chương trình bị treo vô hạn
            response = requests.get(url, timeout=10)
            response.raise_for_status() # Ném ra ngoại lệ nếu mã trạng thái không phải là 200
            return response
        except RequestException as e:
            print(f"Yêu cầu thất bại (Lần thử {attempt + 1}/{max_retries}): {e}")
            if attempt == max_retries - 1:
                raise # Ném ra ngoại lệ nếu lần thử cuối cùng cũng thất bại
            time.sleep(pause)

# Ví dụ sử dụng
try:
    data = fetch_with_retry("https://api.github.com")
    print(f"Yêu cầu thành công, mã trạng thái: {data.status_code}")
except RequestException:
    print("Thất bại sau nhiều lần thử lại, vui lòng kiểm tra mạng hoặc dịch vụ đích.")

Tại sao nó hiệu quả: Nó xử lý sự không ổn định ngẫu nhiên của mạng ngay ở cấp độ code. Lợi ích lớn nhất là ngăn script bị dừng đột ngột chỉ vì một sự cố mạng nhỏ, thực sự đạt được khả năng vận hành "không cần giám sát" — cực kỳ phù hợp cho các tác vụ chạy hàng loạt vào ban đêm.

Đổi Tên File Dựa Trên Nội Dung

Đôi khi tên file không được cập nhật kịp thời, và bạn chẳng biết bên trong có gì. Thay vì mở từng file ra xem rất mất thời gian, bạn có thể viết một script để đọc nội dung và đổi tên chúng. Logic này thường được sử dụng cho hóa đơn, nhật ký (logs) hoặc báo cáo tự động tạo.

import os

TARGET_DIR = "./reports"

def clean_filename(text):
    # Loại bỏ các ký tự không hợp lệ khỏi tên file
    return "".join(c if c.isalnum() else "_" for c in text)[:50]

for filename in os.listdir(TARGET_DIR):
    full_path = os.path.join(TARGET_DIR, filename)
    
    # Đảm bảo chúng ta chỉ xử lý file
    if os.path.isfile(full_path):
        try:
            with open(full_path, "r", encoding='utf-8') as f:
                # Đọc dòng đầu tiên để làm tên file mới
                first_line = f.readline().strip()
                
            if first_line:
                new_name = clean_filename(first_line) + ".txt"
                new_path = os.path.join(TARGET_DIR, new_name)
                
                # Ngăn việc ghi đè lên file đã tồn tại
                if not os.path.exists(new_path):
                    os.rename(full_path, new_path)
                    print(f"Đã đổi tên: {filename} -> {new_name}")
        except Exception as e:
            print(f"Không thể xử lý file {filename}: {e}")

Tại sao nó hiệu quả: Nó giải quyết nỗi đau của những tên file vô nghĩa (như scan_001.txt). Bằng cách đặt tên file dựa trên nội dung cốt lõi, việc tìm kiếm trở nên cực kỳ hiệu quả, loại bỏ nhu cầu phải mở file để xác nhận.

Dọn Dẹp Các File "Zombie" Lâu Ngày Không Truy Cập

Dung lượng ổ đĩa luôn có vẻ bốc hơi một cách bí ẩn, thường là do các file tạm thời bạn tải xuống và không bao giờ mở lại. Script này dọn dẹp các file dựa trên thời gian truy cập cuối cùng của chúng.

import os
import time

WATCH_DIR = "/path/to/cleanup"
EXPIRY_DAYS = 180 # Xóa nếu không truy cập trong 6 tháng
current_time = time.time()

for filename in os.listdir(WATCH_DIR):
    filepath = os.path.join(WATCH_DIR, filename)
    
    if os.path.isfile(filepath):
        # Lấy thời gian truy cập cuối cùng (atime)
        last_access_time = os.path.getatime(filepath)
        
        # Tính khoảng cách thời gian
        if current_time - last_access_time > (EXPIRY_DAYS * 86400):
            try:
                os.remove(filepath)
                print(f"Đã xóa file cũ: {filename}")
            except OSError as e:
                print(f"Xóa thất bại: {e}")

Tại sao nó hiệu quả: Đánh giá dựa trên "thời gian truy cập" thay vì "thời gian tạo" là rất quan trọng vì nó xác định chính xác các file bạn thực sự không cần nữa. Nó hoạt động như một người lao công vô hình, ngăn dữ liệu tạm thời âm thầm "ăn" mất dung lượng ổ đĩa của bạn.

Giám Sát và Tiêu Diệt Các Tiến Trình "Zombie" Tải Cao

Một số script Python (đặc biệt là các script liên quan đến đa tiến trình hoặc máy học) có thể để lại các tiến trình mồ côi (orphan processes) sau khi thoát đột ngột, chiếm dụng CPU. Tìm kiếm thủ công qua Activity Monitor quá chậm; hãy dùng script để tự kiểm tra.

import psutil

# Thiết lập ngưỡng: CPU sử dụng trên 80% và tên tiến trình là python
CPU_THRESHOLD = 80.0
PROCESS_NAME = "python"

for proc in psutil.process_iter(['pid', 'name', 'cpu_percent']):
    try:
        # psutil thường cần một khoảng thời gian để lấy cpu_percent; 
        # sử dụng giá trị tức thời ở đây có thể cần điều chỉnh hoặc vòng lặp giám sát
        if proc.info['name'] and PROCESS_NAME in proc.info['name'].lower():
            if proc.info['cpu_percent'] > CPU_THRESHOLD:
                print(f"Phát hiện tiến trình zombie tải cao PID: {proc.info['pid']} (CPU: {proc.info['cpu_percent']}%)")
                proc.kill()
                print("Đã chấm dứt tiến trình.")
    except (psutil.NoSuchProcess, psutil.AccessDenied):
        pass

Tại sao nó hiệu quả: Đây là một cơ chế phòng thủ chủ động. Nó giải quyết vấn đề rò rỉ bộ nhớ hoặc vòng lặp vô hạn do các script chạy lâu gây ra, ngăn chặn một tiến trình mất kiểm soát làm chậm toàn bộ hệ thống và giúp bạn tiết kiệm thời gian debug thủ công.

"Thuốc Hối Hận" Cho Các Thao Tác: Tự Động Sao Lưu

Sao lưu là bắt buộc trước khi ghi đè lên file cấu hình hoặc dữ liệu quan trọng. Nhưng chúng ta thường hay quên. Hãy để Python lo việc đó.

import shutil
import time
import os

def safe_backup(filepath):
    if not os.path.exists(filepath):
        print(f"File không tồn tại: {filepath}")
        return

    # Tạo tên file sao lưu kèm dấu thời gian
    timestamp = time.strftime("%Y%m%d_%H%M%S")
    backup_path = f"{filepath}.{timestamp}.bak"
    
    try:
        shutil.copy2(filepath, backup_path)
        print(f"Đã tạo bản sao lưu: {backup_path}")
    except IOError as e:
        print(f"Sao lưu thất bại: {e}")
        raise # Sao lưu thất bại thì nên ngắt các thao tác tiếp theo

# Tình huống sử dụng: Trước khi sửa đổi cấu hình
config_file = "app_config.yaml"
safe_backup(config_file)
# Thực hiện thao tác ghi đè tại đây...

Tại sao nó hiệu quả: Bắt buộc sao lưu trước bất kỳ thao tác phá hủy nào (như ghi đè) là quy tắc an toàn cơ bản trong môi trường production, đảm bảo bạn có thể khôi phục ngay lập tức nếu xảy ra lỗi.

Thông Báo Hệ Thống Sau Khi Script Chạy Xong

Nhiều script chạy mất cả nửa tiếng đồng hồ. Bạn không thể cứ nhìn chằm chằm vào màn hình console mãi được. Để script gửi thông báo bật lên (pop-up) khi hoàn thành là một chi tiết nhỏ giúp nâng cao trải nghiệm làm việc.

import platform
import os

def send_notification(title, text):
    system_type = platform.system()
    
    if system_type == "Darwin": # macOS
        # Sử dụng AppleScript để kích hoạt thông báo
        cmd = f"""osascript -e 'display notification "{text}" with title "{title}"'"""
        os.system(cmd)
    elif system_type == "Linux":
        # Linux thường sử dụng notify-send
        cmd = f"""notify-send "{title}" "{text}" """
        os.system(cmd)
    else:
        print(f"Thông báo: [{title}] {text}")

# Mô phỏng tác vụ dài
import time
time.sleep(2)
send_notification("Tác vụ Hoàn tất", "Script xử lý dữ liệu đã thực hiện xong.")

Tại sao nó hiệu quả: Các lập trình viên không cần phải nhìn chằm chằm vào màn hình console đen trắng một cách vô định. Bạn có thể biến thời gian chết "chờ script chạy" thành thời gian tự do; tác vụ sẽ chủ động thông báo cho bạn khi nó hoàn thành.

Thu Thập Dữ Liệu Hạng Nhẹ (Web Scraping)

Khi bạn cần lấy các trường cụ thể (như giá cả hoặc tiêu đề) từ các trang web và sắp xếp chúng thành một bảng, Python là công cụ hiệu quả nhất.

import requests
from bs4 import BeautifulSoup
import csv

def scrape_data(url, output_file):
    # Giả mạo User-Agent để tránh bị chặn bởi các trình chống crawl đơn giản
    headers = {'User-Agent': 'Mozilla/5.0'}
    
    try:
        response = requests.get(url, headers=headers)
        soup = BeautifulSoup(response.content, 'html.parser')
        
        # Giả sử chúng ta muốn lấy tiêu đề và liên kết từ danh sách bài viết
        articles = soup.find_all('article')
        data_rows = []
        
        for article in articles:
            title_tag = article.find('h2')
            if title_tag and title_tag.a:
                title = title_tag.a.text.strip()
                link = title_tag.a['href']
                data_rows.append([title, link])
        
        # Ghi vào file CSV
        with open(output_file, 'w', newline='', encoding='utf-8') as f:
            writer = csv.writer(f)
            writer.writerow(['Tiêu đề', 'Liên kết'])
            writer.writerows(data_rows)
            
        print(f"Đã thu thập thành công {len(data_rows)} mục và lưu vào {output_file}")
        
    except Exception as e:
        print(f"Lỗi trong quá trình thu thập: {e}")

# Ví dụ gọi hàm
# scrape_data("http://example-blog.com", "results.csv")

Tại sao nó hiệu quả: Nó biến hành động "copy-paste" thủ công thành một luồng dữ liệu có cấu trúc. So với làm thủ công, nó xử lý hàng trăm trang trong vài mili-giây, và định dạng dữ liệu tạo ra (như CSV) là thống nhất và sẵn sàng để sử dụng. Quá tiện lợi phải không?

Tự Động Phân Loại File

Tôi không biết máy tính của bạn thế nào, nhưng thư mục Downloads của tôi thường là nơi bừa bộn nhất. Script này tự động di chuyển các file vào các thư mục tương ứng dựa trên đuôi mở rộng của chúng, vì vậy bạn không phải kéo thả thủ công nữa.

import os
import shutil
from pathlib import Path

SOURCE_DIR = Path("/Users/username/Downloads/MixedData")
DEST_DIR = Path("/Users/username/Documents/Sorted")

def organize_files():
    if not SOURCE_DIR.exists():
        return

    for file_path in SOURCE_DIR.iterdir():
        if file_path.is_file():
            # Lấy đuôi mở rộng, ví dụ: .pdf
            ext = file_path.suffix.lower()
            
            if ext: # Bỏ qua các file không có đuôi
                # Bỏ dấu chấm, dùng làm tên thư mục, ví dụ: PDF
                folder_name = ext[1:].upper() + "_Files"
                target_folder = DEST_DIR / folder_name
                
                # Tạo thư mục đích
                target_folder.mkdir(parents=True, exist_ok=True)
                
                # Di chuyển file
                try:
                    shutil.move(str(file_path), str(target_folder / file_path.name))
                    print(f"Đã chuyển: {file_path.name} -> {folder_name}")
                except shutil.Error as e:
                    print(f"Lỗi khi di chuyển file: {e}")

if __name__ == "__main__":
    organize_files()

Tại sao nó hiệu quả: Nó là một chuyên gia sắp xếp kỹ thuật số miễn phí. Sử dụng dữ liệu meta cơ bản nhất — đuôi file — nó ngay lập tức biến một thư mục tải xuống hỗn loạn thành một không gian ngăn nắp, giảm đáng kể gánh nặng nhận thức của việc sắp xếp file thủ công.

Kết Luận

Những script này không phức tạp, nhưng chúng tạo nên nền tảng của một quy trình làm việc tự động hóa. Bắt đầu từ việc thiết lập môi trường với ServBay để giải quyết vấn đề xung đột phiên bản, kết hợp với logic code mạnh mẽ, bạn có thể giao một lượng lớn công việc lặp đi lặp lại tốn thời gian cho máy móc. Một lập trình viên thực thụ không phải là người gõ phím nhanh nhất, mà là người biết cách khiến code làm việc thay cho mình.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí