Thiết kế ứng dụng trích xuất dữ liệu từ các trang web theo kiến trúc hiện đại

Thứ Ba, 18-05-2021
Web Scraping là gì?

Web Scraping là một khái niệm nói về việc trích xuất dữ liệu từ các website khác để phục vụ cho mục đích của ứng dụng mình đang làm.

Web Scraping có rất nhiều ứng dụng trong thực tế, một số ứng dụng có thể kể ra như:

  • Trích xuất và tổng hợp dữ liệu của thị trường chứng khoán;
  • So sách giá cả của các sản phẩm giống nhau ở các sàn mua bán online;
  • Tổng hợp tin tức từ nhiều nguồn báo khác nhau.
Kiến trúc thường thấy của ứng dụng Web Scraping

Trong mô hình này:

  • Websites: là nơi chúng ta cần trích xuất dữ liệu.
  • Jobs: là các ứng dụng Web Scraping, các ứng dụng này sẽ được chạy tự động hay được kích hoạt bằng một ứng dụng khác tùy vào từng trường hợp cụ thể.
  • Storage: sau khi bóc tách dữ liệu từ các nguồn đầu vào, Web Scraping sẽ sinh ra dữ liệu như cấu trúc đã định nghĩa sẵn ở trong ứng dung, dữ liệu đầu ra của quá trình trích xuất dữ liệu có thể được lưu vào file, database,…
  • Data Consumers: dữ liệu đầu ra của các Web Scraping sẽ được khai thác bởi các service đầu cuối nhằm thực hiện mục đích chúng ta muốn làm.
Bạn cần biết gì để làm được 1 Web Scraping?

Để làm 1 ứng dụng Web Scraping, bạn cần biết ít nhất một ngôn ngữ lập trình phía Back End như: Java, Javascript (NodeJS),… và cần biết thêm một khái niệm khá quan trọng ở phía Front End là Selector.

Bạn có thể đọc một số định nghĩa về Selector ở https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors

Bạn có thể hiểu khái quát như sau: Selector là thuật ngữ để chỉ cách bạn có thể xác định được một thẻ bất kỳ ở bên trong một website, từ đó bạn có thể lấy được nội dung mong muốn tại bất kỳ một vị trí nào trên web site.

Bạn xem hình minh họa ở trên, tác giả đang sử dụng công cụ phát triển của trình duyệt Chrome để lấy selector của title của tin tức đầu tiền trong trang tin https://vnexpress.net/. Selector bạn lấy từ công cụ phát triển của Chrome cũng chính là selector mà bạn cần thiết để làm Web Scraping, bạn có thể xem chi tiết hơn ở phần code mẫu tiếp theo.

Lưu ý: Tính ổn định của nội dung tại một selector phụ thuộc vào trang web nguồn, có những trang web sẽ không thay đổi nội dung được hiển thị tại vị trí đã xác định trước, nhưng có những trang web có nội dung thay đổi cùng với 1 selector: Nghĩa là bạn sẽ có nội dung khác nhau giữa các lần lấy dữ liệu cho cùng 1 selector.

Làm sao để có thể thiết kế được một Web Scraping hiệu quả?

Ngày nay, với sự hỗ trợ mạnh mẽ từ công nghê, việc thiết kế một Web Scraping không quá khó, tuy nhiên điều đó không có nghĩa là chúng ta không còn vấn đề gì cần cân nhắc, như: ứng dụng Web Scraping của chúng ta chạy ở đâu, cần bao nhiêu tài nguyên CPU, cần bao nhiêu tài nguyên bộ nhớ, chi phí hàng tháng thế nào,… để trả lời được câu hỏi đó thì chúng ta cần phải xác định được nguồn dữ liệu thế nào, yêu cầu dữ liệu cần trích xuất là gì, lưu trữ ở đâu, dùng công nghệ gì để làm,…

Như nói ở trên chúng ta có nhiều cách để làm, trong bài này tác giả sẽ dùng Javascript (NodeJS) để làm ví dụ và phân tích tính hiệu quả của quá trình hoạt động.

Qua làm nhiều ứng dụng về Web Scraping, theo kinh nghiệm của tác giả thì có 3 loại nguồn web chính (nguồn dữ liệu để bóc tách):

  1. Web tĩnh: đây là loại web mà sau khi được tải về thì chúng ta có đầy đủ hết nội dung cần biết trên trang đó. Các trang tin tức thường thiết kế theo dạng này.
  2. Web động: loại này khác với loại web tĩnh là dữ liệu tải về lần đầu tiên không được đầy đủ, dữ liệu sẽ được tiếp tục tải về và điền đầy đủ vào sau đó. Hoặc dữ liệu liên tục thay đổi như các trang chat online, bán đấu giá, chứng khoán, các ứng dụng SPA,…
  3. Loại cuối cùng không những chứa dữ liệu động mà còn yêu cầu chạy trên nền Browser thực, thực thi các API của Browser, cần lưu cookie, lưu dữ liệu tạm ở local storage,…

Tương ứng với 3 loại trên thì chúng ta sẽ có những cách làm và thư viện tương ứng để thực hiện việc trích xuất dữ liệu cũng như chiến lược triển khai để giảm thiểu chi phí nhất.

  1. Loại 1: với loại này bạn không cần quá nhiều bộ nhớ để lưu trữ cũng như CPU không cần quá mạnh, tất cả bạn cần là đọc nội dung của trang web nguồn, trích xuất dữ liệu cần và lưu lại vào bộ lưu trữ để sử dụng sau này.

Thư viện bạn có thể sử dụng cho loại website này là: Cheerio

  1. Loại 2: để trích xuất được dữ liệu động từ 1 website hay trích xuất dữ liệu đang thay đổi tại một thời điểm nào đó bạn cần có một thư viện có thể hiểu được và thực thi được các lệnh liên quan đến HTML và Javascript. Cũng vì yêu cầu đó nên ứng dụng cần tải nội dung trang web vào bộ nhớ máy tính để phân tích và thực thi lệnh nên cần chiếm nhiều bộ nhớ hơn và CPU hơn.

Thư viện bạn có thể sử dụng cho loại này là: JSDom

  1. Loại 3: khi một website đòi hỏi thực thi các API thực của Browser thì các trình duyệt ảo không đáp ứng được, mà chúng ta cần chạy website đó trên các Browser thực để đưa ra kết quả chính xác nhất.

Thư viện bạn có thể sử dụng là: Puppeteer

Tại sao tác giả lại đưa ra các thư viện khác nhau cho các loại web khác nhau? Câu trả lời là để tiết kiệm chi phí. 3 thư viện mà tác giả nói ở trên bản thân nó có nhiều đặc điểm khác nhau và sử dụng cho mục đích khác nhau:

  1. Cheerio: đây là thư viện giúp bạn duyệt, xử lý các thẻ HTML, các định nghĩa CSS tĩnh. Thư viện này khá nhỏ và không yêu cầu bất kỳ thư viện đặc biệt nào khác. Vì lý do đó nên ứng dụng Web Scraping sử dụng Cheerio dễ dàng đóng gói và triển khai cùng với Docker để tiết kiệm chi phí triển khai và vận hành.
  2. JSDom: thư viện này hoạt động như một trình duyệt ảo, nó có thể đọc nội dung 1 trang web, thực thi các lệnh Javascript, CSS,… thực hiện sinh mã HTML tương ứng. So với Cheerio thì JSDom linh hoạt hơn, thực hiện được nhiều việc hơn và cũng chiếm nhiều bộ nhớ cũng như CPU hơn. JSDom cũng không đòi hỏi bất kỳ một thư viện đặc biệt nào khác nên nếu muốn bạn có thể thiết kế theo hướng Docker để tiết kiệm chi phí.
  3. Puppeteer: là một thư viện do Google phát triển, nó cung cấp API để điều khiển Chrome hoặc Chromium thông qua DevTools Protocol, Puppeteer cung cấp 2 chế độ là headless và non-headless. Bởi vì việc sử dụng Peppeteer cần thực hiện với một trình duyệt thực nên khi chạy bạn cần có các thư viện đặc thù, thông thường bạn sẽ không thấy gì trở ngại nếu chạy Puppeteer trên các server Ubuntu hay tương đương, tuy nhiên khi bạn chạy Puppeteer ở môi trường Docker hay Serverless thì sẽ có khá nhiều vấn đề về cấu hình nên nếu ứng dụng thiết kế với Puppeteer bạn nên chọn phương án là chạy với máy ảo. Và đây cũng là phương án tốn nhiều chi phí nhất.
Kết quả test cho 3 cách thiết kế đã nói

Để thấy rõ hơn hiệu quả hoạt động của 3 cách thiết kế trên, tác giả đã chạy thử 1 bộ test trên môi trường GCP với 3 máy giống nhau n1-standard-1 tại cùng 1 thời điểm, kết quả như hình sau:

  • webscraping: là ứng dụng được viết với Cheerio.
  • webscraping-jsdom: là ứng dụng được viết với Jsdom.
  • webscraping-puppeteer: là ứng dụng được viết với Puppeteer.
DEMO

Phần DEMO này bạn có thể chạy ở bất kỳ máy tính nào đã có sẵn môi trường NodeJS. Bạn cần lấy source code từ github để tiếp tục; và cần chú ý, source code chứa 3 nhánh tương ứng với source code cho 3 thư viện đã nói ở trên.

Sau khi đã checkout nhánh bạn mong muốn, bạn chạy lệnh sau để tiếp tục:

> npm install

> node index.js

Nếu quá trình cài đặt thành công, bạn sẽ thấy kết quả như hình sau (với nhánh Puppeteer):

Kết luận

Trích xuất dữ liệu từ các trang web để phục vụ cho mục đích của dự án không phải là vấn đề mới tuy nhiên với sự thay đổi của công nghệ thì cách làm ở mỗi giai đoạn sẽ khác nhau. Lựa chọn công nghệ nào để phát triển sản phẩm tùy thuộc vào nhiều yếu tố như yêu cầu dự án, đội ngũ nhà phát triển, chi phí dự án,… thông qua bài viết này tác giả hy vọng cung cấp đến đọc giả cái nhìn tổng quát về trích xuất dữ liệu cũng như một vài ví dụ dựa trên nền tảng Cloud để bạn có thêm lựa chọn.

Trần Hữu Lập – FPT Software

share