Giới thiệu
File .docx thực chất là file ZIP chứa XML. Thư viện python-docx chủ yếu dùng để tạo file Word, đọc nội dung phức tạp (bảng, hình ảnh, định dạng) hỗ trợ hạn chế. Cách tiếp cận cấp thấp: giải nén ZIP, đọc file word/document.xml.
Cài đặt
pip install python-docx # Dùng cho phương pháp 2
Phương pháp 1: Đọc XML trực tiếp (low-level)
Phù hợp khi cần truy xuất toàn bộ nội dung thô, không phụ thuộc python-docx.
from zipfile import ZipFile
from urllib.request import urlopen
from io import BytesIO
# Đọc file Word từ URL (hoặc local file)
file_url = 'https://file-examples-com.github.io/uploads/2017/02/file-sample_100kB.docx'
word_bytes = urlopen(file_url).read()
word_file = BytesIO(word_bytes)
# Giải nén và đọc document.xml
document = ZipFile(word_file)
xml_content = document.read('word/document.xml')
print(xml_content.decode('utf-8'))
Kết quả: XML thô chứa toàn bộ nội dung văn bản trong thẻ <w:t>, kèm định dạng phức tạp (namespace w:, style, font, bảng, hyperlink, hình ảnh...).
Phương pháp 2: Dùng python-docx (high-level, chỉ text cơ bản)
import docx
doc = docx.Document('file.docx')
# Đọc tất cả paragraph
for i, para in enumerate(doc.paragraphs):
if para.text.strip():
print(f'Para {i}: {para.text}')
# Đọc bảng
for table in doc.tables:
for row in table.rows:
cells = [cell.text for cell in row.cells]
print(' | '.join(cells))
So sánh
| Đặc điểm | XML trực tiếp | python-docx |
|---|---|---|
| Nội dung text | Đầy đủ (kể cả trong table, header, footer) | Chỉ paragraph thông thường |
| Định dạng | XML thô, khó xử lý | Đã parse (bold, italic, style) |
| Bảng (table) | Phải parse XML table | Hỗ trợ tốt doc.tables |
| Hình ảnh | Trong XML relationship | Hỗ trợ trích xuất |
| Phức tạp triển khai | Cao | Thấp |
Khi nào dùng cách nào?
- python-docx: Cần đọc text đơn giản, bảng, trích xuất hình ảnh, sửa đổi file.
- XML trực tiếp: Cần toàn bộ nội dung thô, xử lý batch, không muốn cài thư viện nặng, hoặc python-docx bỏ lỡ nội dung.
Mẹo: Tìm text trong XML
import xml.etree.ElementTree as ET
root = ET.fromstring(xml_content)
# Namespace
ns = {'w': 'https://schemas.openxmlformats.org/wordprocessingml/2006/main'}
# Tìm tất cả w:t (text)
texts = [elem.text for elem in root.findall('.//w:t', ns) if elem.text]
print(' '.join(texts))