Xây dựng công cụ cào dữ liệu truyện chữ bằng Python

Việc tự động hóa quá trình thu thập nội dung từ các trang web truyện chữ là một bài tập thực hành phổ biến để làm quen với kỹ thuật Web Scraping. Bằng cách sử dụng ngôn ngữ Python cùng các thư viện như requestsBeautifulSoup, chúng ta có thể dễ dàng trích xuất hàng ngàn chương truyện một cách nhanh chóng.

1. Thu thập danh sách liên kết các chương

Bước đầu tiên trong quá trình này là truy cập vào trang mục lục của bộ truyện để lấy toàn bộ URL của các chương đơn lẻ. Chúng ta sẽ sử dụng CSS Selector để định vị chính xác các thẻ chứa liên kết.

import requests
from bs4 import BeautifulSoup

def get_all_chapters(index_url):
    # Gửi yêu cầu HTTP đến trang mục lục
    response = requests.get(index_url)
    response.encoding = 'utf-8'  # Đảm bảo hiển thị đúng font chữ
    
    soup = BeautifulSoup(response.text, 'lxml')
    # Tìm tất cả các thẻ a trong cấu trúc danh sách chương
    raw_links = soup.select('#list dl dd a')
    
    base_domain = "http://www.biquge.com.tw"
    processed_urls = []
    
    for link in raw_links:
        path = link.get('href')
        # Hợp nhất path với domain để tạo URL hoàn chỉnh
        full_path = base_domain + path
        processed_urls.append(full_path)
        
    return processed_urls

2. Trích xuất nội dung văn bản và lưu trữ

Sau khi có được danh sách URL, chương trình sẽ lặp qua từng liên kết để lấy tiêu đề chương và nội dung truyện, sau đó ghi trực tiếp vào tệp tin văn bản (txt).

def save_content(chapter_url, output_file):
    res = requests.get(chapter_url)
    res.encoding = 'utf-8'
    soup = BeautifulSoup(res.text, 'lxml')
    
    # Trích xuất tiêu đề chương từ thẻ h1
    chapter_title = soup.find('div', class_='bookname').h1.get_text()
    
    # Trích xuất nội dung truyện từ thẻ div có id content
    chapter_body = soup.find('div', id='content').get_text()
    
    # Ghi dữ liệu vào file bằng phương thức 'a' (append) để không ghi đè
    with open(output_file, 'a', encoding='utf-8') as f:
        f.write(f"\n{chapter_title}\n")
        f.write("-" * 20 + "\n")
        f.write(chapter_body + "\n")

3. Vận hành chương trình

Chúng ta kết hợp hai hàm trên vào luồng thực thi chính. Để tránh bị chặn bởi máy chủ, bạn có thể cân nhắc thêm các khoảng nghỉ (delay) giữa các lần gọi yêu cầu.

if __name__ == '__main__':
    target_index = 'http://www.biquge.com.tw/18_18049/'
    file_name = 'truyen_da_tai.txt'
    
    all_links = get_all_chapters(target_index)
    print(f"Tìm thấy {len(all_links)} chương. Đang bắt đầu tải dữ liệu...")
    
    for url in all_links:
        try:
            save_content(url, file_name)
            print(f"Hoàn thành: {url}")
        except Exception as e:
            print(f"Xảy ra lỗi tại {url}: {e}")

Tối ưu hóa với XPath

Mặc dù BeautifulSoup rất thân thiện, nhưng khi đối mặt với các cấu trúc HTML phức tạp hoặc yêu cầu hiệu năng cao hơn, sử dụng lxml kết hợp với XPath sẽ mang lại tốc độ xử lý vượt trội. XPath cho phép bạn truy vấn sâu vào các node với cú pháp ngắn gọn hơn.

Ví dụ, để lấy trực tiếp thuộc tính href của danh sách chương, bạn có thể sử dụng biểu thức:

# Sử dụng thư viện lxml.etree
# links = tree.xpath('//*[@id="list"]/dl/dd/a/@href')

Việc sử dụng XPath đặc biệt hiệu quả khi bạn muốn xác định các phần tử dựa trên thuộc tính class hoặc vị trí tương đối giữa các thẻ trong DOM.

Thẻ: python web-scraping BeautifulSoup requests lxml

Đăng vào ngày 14 tháng 7 lúc 01:41