Cách dễ nhất để thu thập dữ liệu web bằng Python

Nội dung

    NODRIVER là công cụ tự động hóa trình duyệt dựa trên Python. Nó cho phép mở các trang web, tương tác và thu thập dữ liệu thông qua mã code. NODRIVER không phụ thuộc vào Selenium hoặc Puppeteer. Nó cũng không sử dụng ChromeDriver. Thay vào đó, nó sử dụng phương pháp riêng để kiểm soát trình duyệt.

    Điều này mang lại một số lợi thế quan trọng:

    • Nó tránh bị phát hiện tốt hơn các công cụ truyền thống.
    • Nó yêu cầu ít thiết lập hơn.
    • Nó hỗ trợ lập trình bất đồng bộ (async) hiện đại.

    Cải thiện Trích xuất Dữ liệu với Máy chủ MCP

    Nếu cần giải pháp đơn giản và rẻ cho việc trích xuất web quy mô lớn hoặc phức tạp, hãy cân nhắc sử dụng Giao thức Ngữ cảnh Mô hình (MCP) của Bright Data. Điều này bao gồm các trang web có CAPTCHA hoặc bảo vệ chống bot nâng cao.

    Tôi không có liên kết với Bright Data. Tôi chỉ thực sự thích sử dụng máy chủ MCP của họ. Máy chủ MCP của Bright Data cung cấp quyền truy cập vào TẤT CẢ các sản phẩm của họ từ một nơi duy nhất.

    Hãy kiểm tra tất cả các công cụ có sẵn như Selenium, Playwright và Puppeteer đã có mặt. Bây giờ, chúng ta quay lại với NODRIVER.

    Tại sao nên Sử dụng NODRIVER cho Web Scraping?

    Nhiều công cụ như Selenium, Playwright và Puppeteer đã tồn tại.

    Vậy tại sao các doanh nghiệp nên cân nhắc NODRIVER?

    1. Không cần Trình điều khiển bên ngoài: Các công cụ truyền thống như Selenium cần ChromeDriver.Việc cài đặt và cập nhật ChromeDriver có thể gây khó chịu.NODRIVER không cần bất kỳ trình điều khiển nào.Bạn chỉ cần Python và một trình duyệt dựa trên Chrome (như Chrome hoặc Brave).
    2. Thiết lập Đơn giản: Cài đặt NODRIVER chỉ cần một lệnh duy nhất:pip install nodriverKhông cần thiết lập bổ sung nào khác. Tạo virtual environment (khuyến nghị) để tránh xung đột thư viện:
      python3 -m venv venv_nodriver
      source venv_nodriver/bin/activate
      Bạn không phải xử lý các đường dẫn phức tạp hoặc biến hệ thống.
    3. Thiết kế Bất đồng bộHầu hết các thư viện trích xuất dữ liệu đều đồng bộ.Điều này có nghĩa là chúng chạy từng tác vụ một.NODRIVER sử dụng các hàm bất đồng bộ (async functions).Điều này cho phép thực hiện nhiều việc hơn trong thời gian ngắn hơn.Nó hoàn hảo cho việc trích xuất nhiều trang cùng một lúc.
    4. Tránh Phát hiện Tốt hơnCác trang web ngày càng thông minh hơn trong việc phát hiện bot.NODRIVER không tuân theo các mẫu giống như Selenium hoặc Puppeteer.Do đó, nó có thể tránh bị phát hiện trong một số trường hợp.

    Thiết lập Script NODRIVER đầu tiên

    Đây là các bước để trích xuất dữ liệu từ một trang web đơn giản bằng NODRIVER.

    Bước 1: Cài đặt NODRIVER

    Mở terminal và chạy lệnh:

    pip install nodriver

    Đảm bảo bạn đã cài đặt Python 3.7+.

    Bước 2: Viết Script Cơ bản

    Phiên bản của nodriver mà đang dùng (ví dụ pip show nodriver cho ra "Version: x.y.z". Ví dụphiên bản 0.47.0. Dưới đây là bản script Python đã chỉnh sửa đúng API (theo tài liệu cho phiên bản đó) và phù hợp với cấu trúc bạn muốn:

    import nodriver as uc
    import asyncio

    async def main():
    # Khởi trình duyệt với các tham số cần nếu cần (headless, no sandbox,…)
    browser = await uc.start(headless=True, sandbox=False, args=[
    “–no-sandbox”,
    “–disable-dev-shm-usage”,
    “–disable-gpu”
    ])

    try:
    page = await browser.get(“//quotes.toscrape.com”)
    quotes = await page.select_all(“div.quote”)

    for quote in quotes:
    text_elem = await quote.query_selector(“span.text”)
    author_elem = await quote.query_selector(“small.author”)

    text = text_elem.text if text_elem else None
    author = author_elem.text if author_elem else None

    print(f”{text} – {author}”)

    await page.close()

    except Exception as e:
    print(“Lỗi:”, e)

    finally:
    # Đóng browser — theo tài liệu cho phiên bản này dùng browser.close()
    try:
    await browser.close()
    except Exception:
    pass

    if __name__ == ‘__main__’:
    uc.loop().run_until_complete(main())

    Script này mở trình duyệt, truy cập trang web //example.com, sau đó đóng trình duyệt.

    Điều hướng Trang và Thu thập Dữ liệu

    Bây giờ chúng ta sẽ đi sâu hơn vào cách thu thập dữ liệu thực tế.

    Ví dụ: Trích xuất Trích dẫn từ một Trang Web

    Giả sử bạn muốn thu thập các trích dẫn từ trang web //quotes.toscrape.com.

    Trang này được tạo ra để thực hành trích xuất dữ liệu.

    Đây là cách thu thập tất cả các trích dẫn trên một trang:

    import nodriver
    async def main():
        browser = await nodriver.start()
        page = await browser.get("//quotes.toscrape.com")
        quotes = await page.select_all("div.quote")
        for quote in quotes:
            text = (await quote.query_selector("span.text")).text
            author = (await quote.query_selector("small.author")).text
            print(f"{text} - {author}")
        await page.close()
    if __name__ == '__main__':
        nodriver.loop().run_until_complete(main())

    Xử lý Nhiều Trang (Phân trang)

    Nhiều trang web chia dữ liệu thành nhiều trang riêng biệt.

    Đây được gọi là phân trang.

    Để xử lý điều này, bạn cần phát hiện nút “Next”.

    Bạn phải tiếp tục truy cập các trang mới cho đến khi nút “Next” biến mất.

    Đây là cách thực hiện:

    import nodriver
    async def main():
        browser = await nodriver.start()
        base_url = "//quotes.toscrape.com"
        next_url = "/"
        while next_url:
            page = await browser.get(base_url + next_url)
            quotes = await page.select_all("div.quote")
            for quote in quotes:
                text = (await quote.query_selector("span.text")).text
                author = (await quote.query_selector("small.author")).text
                print(f"{text} - {author}")
            next_btn = await page.select("li.next > a")
            if next_btn:
                attrs = next_btn.attributes
                for i in range(len(attrs)):
                    if attrs[i] == "href":
                        next_url = attrs[i+1]
                        break
            else:
                next_url = None
            await page.close()
    if __name__ == '__main__':
        nodriver.loop().run_until_complete(main())

    Phiên bản này đi qua tất cả các trang và in ra mọi trích dẫn tìm thấy.

    Trích xuất và Lưu trữ Dữ liệu

    Bạn có thể lưu dữ liệu vào một tệp thay vì chỉ in ra.

    JSON là một định dạng tốt cho việc lưu trữ dữ liệu có cấu trúc.

    Đây là cách lưu các trích dẫn đã trích xuất vào tệp JSON:

    import nodriver
    import json
    async def main():
        browser = await nodriver.start()
        base_url = "//quotes.toscrape.com"
        next_url = "/"
        data = []
        while next_url:
            page = await browser.get(base_url + next_url)
            quotes = await page.select_all("div.quote")
            for quote in quotes:
                text = (await quote.query_selector("span.text")).text
                author = (await quote.query_selector("small.author")).text
                tags = [tag.text for tag in await quote.query_selector_all("a.tag")]
                data.append({
                    "quote": text,
                    "author": author,
                    "tags": tags
                })
            next_btn = await page.select("li.next > a")
            if next_btn:
                attrs = next_btn.attributes
                for i in range(len(attrs)):
                    if attrs[i] == "href":
                        next_url = attrs[i+1]
                        break
            else:
                next_url = None
            await page.close()
        with open("quotes.json", "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=4)
    if __name__ == '__main__':
        nodriver.loop().run_until_complete(main())

    Sau khi chạy script, bạn sẽ nhận được tệp quotes.json chứa tất cả nội dung đã trích xuất.

    Những Thách thức Hiện tại với NODRIVER

    NODRIVER là một công cụ mới.

    Điều này đồng nghĩa với việc có một số lỗi và thiếu sót tính năng.

    1. Chế độ Không đầu (Headless Mode) có thể không hoạt độngChạy NODRIVER mà không hiển thị trình duyệt đôi khi bị lỗi.Đây có thể là một lỗi hoặc một tính năng để tránh phát hiện bot.
    2. Trích xuất Thuộc tính không mượt màKhi lấy thuộc tính của một phần tử, NODRIVER trả về một danh sách (list) thay vì một từ điển.Điều này làm cho việc xử lý trở nên khó khăn.Ví dụ, attrs = element.attributes trả về [‘href’, ‘/page/2/’].Người dùng phải lặp qua danh sách này để tìm thuộc tính cần thiết.
    3. Hỗ trợ Proxy Hạn chếSử dụng proxy là cần thiết cho việc trích xuất dữ liệu nghiêm túc.NODRIVER có phương thức create_context().Tuy nhiên, tài liệu hướng dẫn không đầy đủ.Hiện tại, tính năng này hoạt động không ổn định.Nó có thể hoạt động tốt hơn trong tương lai.

    Các Trường hợp Sử dụng Tốt cho NODRIVER

    NODRIVER rất phù hợp cho các mục đích sau:

    • Học cách trích xuất dữ liệu bất đồng bộ.
    • Tránh các cơ chế phát hiện bot đơn giản.
    • Trích xuất dữ liệu từ các trang web nhỏ hơn.
    • Kiểm tra ý tưởng nhanh chóng.

    Nếu dự án phức tạp liên quan đến quy trình đăng nhập, CAPTCHA, hoặc cấm IP, bạn vẫn cần Selenium hoặc Playwright.

    Các Công cụ Thay thế cho NODRIVER

    Nếu NODRIVER không đáp ứng nhu cầu, đây là các công cụ vững chắc khác:

    • PlaywrightHoàn toàn bất đồng bộ.Hỗ trợ chế độ không đầu.Hỗ trợ tích hợp sẵn cho việc chờ đợi, xác thực và tải xuống tệp.
    • SeleniumRất trưởng thành và ổn định.Hỗ trợ nhiều trình duyệt.Có cộng đồng lớn và nhiều hướng dẫn.
    • ScrapyTốt nhất cho việc trích xuất dữ liệu quy mô lớn.Hoạt động với bộ chọn (selectors) và pipelines.Được xây dựng để thu thập dữ liệu từ nhiều trang và lưu trữ.

    Tương lai của NODRIVER

    NODRIVER vẫn đang phát triển.

    Nhà phát triển của nó cũng là người tạo ra Undetected Chromedriver.

    Undetected Chromedriver nổi tiếng vì khả năng tránh phát hiện bot.

    Kinh nghiệm này cho thấy NODRIVER sẽ ổn định hơn theo thời gian.

    Các tính năng dự kiến sớm xuất hiện bao gồm:

    • Xử lý thuộc tính tốt hơn.
    • Hỗ trợ proxy đầy đủ.
    • Cải thiện tương tác trang như nhấp chuột và gõ phím.
    • Chế độ không đầu hoạt động ổn định.

    Kết luận

    Trích xuất web vào năm 2025 nhanh hơn và dễ dàng hơn với các công cụ như NODRIVER.

    Nó cho phép xây dựng các trình trích xuất đơn giản và nhanh chóng với thiết lập tối thiểu.

    NODRIVER nhẹ và dễ sử dụng.

    Nó hoạt động mà không cần Selenium hoặc Puppeteer.

    Điều này làm cho nó tuyệt vời cho các dự án nhỏ hoặc học tập trích xuất bất đồng bộ.

    Tuy nhiên, nó vẫn có một số lỗi và hạn chế.

    Nó chưa hoàn toàn hỗ trợ proxy, CAPTCHA, hoặc chế độ không đầu.

    Đối với các nhu cầu nâng cao hơn, các công cụ như Playwright hoặc Selenium là lựa chọn tốt hơn.

    Nếu bạn muốn kiểm tra ý tưởng nhanh chóng, NODRIVER là một lựa chọn tuyệt vời.

    Đây là một trong những công cụ trích xuất dữ liệu thú vị nhất hiện nay.

    Tham khảo: medium.com

    n8n không chạy Python, nên bạn có thể:

    Gọi script Python này bằng Execute Command Node trong n8n.

    Hoặc dùng Webhook để n8n gọi API do Python (chạy nodriver) cung cấp.

    Kết quả (HTML, ảnh, dữ liệu) có thể đẩy ngược lại n8n để xử lý tiếp.

    [HTTP Trigger] → [Execute Command: python3 scraper.py] → [Set / Transform data] → [Send Telegram]

    Tránh dùng trình duyệt giúp workflow chạy nhanh hơn và ổn định hơn (đặc biệt trên máy yếu như Orange Pi).

    Chạy lệnh như: python3 scraper.py //quotes.toscrape.com

    import nodriver as uc
    import asyncio
    import sys
    import json

    async def main():
    if len(sys.argv) < 2:
    print(“Usage: python3 scraper.py <URL>”)
    return

    url = sys.argv[1].strip()
    if not (url.startswith(“//”) or url.startswith(“//”)):
    print(“URL không hợp lệ, vui lòng nhập đường dẫn dạng // hoặc //”)
    return

    # Khởi trình duyệt
    browser = await uc.start(headless=True, sandbox=False, args=[
    “–no-sandbox”,
    “–disable-dev-shm-usage”,
    “–disable-gpu”
    ])

    try:
    page = await browser.get(url)
    quotes = await page.select_all(“div.quote”)

    for quote in quotes:
    text_elem = await quote.query_selector(“span.text”)
    author_elem = await quote.query_selector(“small.author”)

    text = text_elem.text if text_elem else None
    author = author_elem.text if author_elem else None

    print(f”{text} — {author}”)

    await page.close()

    except Exception as e:
    print(“Có lỗi xảy ra:”, e)

    finally:
    try:
    await browser.close()
    except Exception:
    pass

    if __name__ == ‘__main__’:
    uc.loop().run_until_complete(main())

    • Script sẽ mở browser headless, truy cập URL, tìm các phần tử div.quote, in mỗi câu trích dẫn + tác giả ra terminal.

    • Sau khi hoàn tất, browser sẽ đóng lại.

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

    Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

    Chat with us
    Hello! How can I help you today?