Xử lý bảng HTML và xuất dữ liệu sang Excel bằng Python

Khi làm việc với dữ liệu từ web, việc trích xuất nội dung bảng HTML và lưu dưới dạng tệp Excel là một nhu cầu phổ biến. Bài viết này trình bày cách thực hiện tự động hóa quy trình này bằng các thư viện Python tiêu chuẩn.

Yêu cầu hệ thống

Cài đặt ba thư viện cần thiết:

  • bs4 (Beautiful Soup) — phân tích cú pháp tài liệu HTML/XHTML
  • pandas — xử lý cấu trúc dữ liệu dạng bảng
  • openpyxl — ghi định dạng Excel (.xlsx)

Chạy lệnh sau để cài đặt:

pip install beautifulsoup4 pandas openpyxl

Phân tích bảng HTML

Giả sử có một đoạn HTML chứa bảng đơn giản như sau:

<html>
<body>
<table border="1">
  <thead>
    <tr><th>Họ tên</th><th>Tuổi</th><th>Nghề nghiệp</th></tr>
  </thead>
  <tbody>
    <tr><td>Nguyễn Văn A</td><td>28</td><td>Lập trình viên</td></tr>
    <tr><td>Trần Thị B</td><td>32</td><td>Thiết kế đồ họa</td></tr>
  </tbody>
</table>
</body>
</html>

Đoạn mã sau đọc nội dung HTML, xác định tất cả các bảng, rồi trích xuất tiêu đề và dữ liệu từng hàng:

from bs4 import BeautifulSoup

def extract_html_tables(html_path):
    with open(html_path, "r", encoding="utf-8") as file:
        doc = BeautifulSoup(file, "html.parser")
    
    tables = []
    for table_tag in doc.find_all("table"):
        # Lấy tiêu đề từ <th> trong <thead> hoặc hàng đầu tiên
        header_row = table_tag.find("thead")
        if not header_row:
            header_row = table_tag.find("tr")
        
        headers = [th.get_text(strip=True) for th in (header_row.find_all("th") or header_row.find_all("td"))] if header_row else []
        
        # Lấy dữ liệu từ <tbody> hoặc các hàng <tr> còn lại
        body = table_tag.find("tbody") or table_tag
        rows = body.find_all("tr")
        data_rows = []
        
        for row in rows:
            cells = row.find_all(["td", "th"])
            if cells and not all(cell.get_text(strip=True) == "" for cell in cells):
                data_rows.append([cell.get_text(strip=True) for cell in cells])
        
        # Loại bỏ hàng tiêu đề nếu đã được lấy ở trên
        if headers and data_rows and data_rows[0] == headers:
            data_rows = data_rows[1:]
            
        tables.append({"headers": headers, "rows": data_rows})
    
    return tables

Xuất ra tệp Excel

Sau khi thu thập dữ liệu, dùng pandas để tạo DataFrame và ghi vào tệp Excel:

import pandas as pd

def save_tables_to_excel(tables, base_name="exported_table"):
    for idx, tbl in enumerate(tables, 1):
        if not tbl["headers"] or not tbl["rows"]:
            continue
            
        df = pd.DataFrame(tbl["rows"], columns=tbl["headers"])
        filename = f"{base_name}_{idx}.xlsx"
        df.to_excel(filename, index=False, engine="openpyxl")
        print(f"Đã lưu bảng {idx} vào {filename}")

# Sử dụng
tables_data = extract_html_tables("data.html")
save_tables_to_excel(tables_data, "bang_du_lieu")

Mở rộng chức năng

Để xử lý nhiều bảng trong cùng một tệp HTML và đảm bảo tính ổn định với cấu trúc không đồng nhất, có thể thêm kiểm tra lỗi và chuẩn hóa dữ liệu:

def robust_table_export(html_path, output_prefix="sheet"):
    try:
        tables = extract_html_tables(html_path)
        if not tables:
            print("Không tìm thấy bảng nào trong tài liệu.")
            return
        
        with pd.ExcelWriter(f"{output_prefix}.xlsx", engine="openpyxl") as writer:
            for i, t in enumerate(tables, 1):
                if t["headers"] and t["rows"]:
                    df = pd.DataFrame(t["rows"], columns=t["headers"])
                    sheet_name = f"Bang_{i}"[:31]  # Giới hạn tên sheet Excel
                    df.to_excel(writer, sheet_name=sheet_name, index=False)
        print(f"Xuất thành công {len(tables)} bảng vào {output_prefix}.xlsx")
    except Exception as e:
        print(f"Lỗi khi xuất: {e}")

Thẻ: beautifulsoup4 Pandas openpyxl html-parsing excel-export

Đăng vào ngày 20 tháng 5 lúc 07:50