Hướng dẫn goutte php - thả php
Giới thiệuThuật ngữ cào dữ liệu hay crawl data chắc chắn không còn xa lạ gì mọi người. Nó đơn giản là tự động hóa việc trích xuất thông tin từ một nguồn nào đó, cụ thể ở bài viết này là một website. Công việc này hoàn toàn có thể thực hiện bằng tay, nếu bạn có đủ thời gian và kiên nhẫn. Tuy nhiên để không phải ngồi hàng giờ liền click và copy past, bài viết này sẽ hướng dẫn cách viết một ứng dụng cào dữ liệu đơn giản. Show Mục tiêu được (hoặc bị) cào dữ liệu hôm nay là trang bán điện thoại của thế giới di động. Tại link. Dữ liệu sau khi cào sẽ được lưu vào database. Chuẩn bịĐầu tiên bạn cần khởi tạo một ứng dụng Laravel và config kết nối đến databasse. Tiếp đến, chạy đoạn lệnh sau để cài đặt thư viện Goutte
Goutte là một thư viện hỗ trợ việc crawl website rất hiệu quả. Migrations và ModelsĐể không làm cho ứng dụng trở nên quá phức tạp, với mỗi sản phẩm, ta chỉ cần lấy 3 thông tin là: tên, giá và số sao được đánh giá. Database tương ứng chỉ có một bảng duy nhất. Chạy lệnh sau để tạo 2 file model và migrations cho bảng 7.
Hàm up() trong file migration sẽ có nội dung như sau:
Đối với model ở file App\Product.php, chúng ta giữ nguyên không cần thay đổi gì. Quá trình khởi tạo cho database kết thúc bằng việc chạy migration. Lưu ý đảm bảo rằng MySQL (hoặc bất cứ database nào các bạn sử dụng) đang chạy và các thông tin kết nối DB ở file .env đã được điền đầy đủ và chính xác.
Viết web scraperBắt đầuBot sẽ không được viết vào controller hay model, thay vào đó, bạn tạo một file mới tại App/Scraper/TGDD.php với nội dung như sau:
Tất cả nội dung của web scraper đơn giản mà chúng ta sẽ viết gói gọn ở hàm scrape() này. Tìm hiểu cấu trúc HTML của websiteMuốn cào dữ liệu từ một website, trước tiên ta phải hiểu cấu trúc HTML của website đó được tổ chức thế nào. Điều này cũng đồng nghĩa, nếu có bất kì cập nhật nào của chủ website, làm thay đổi cấu trúc HTML thì scraper của ta có khả năng ở nên vô dụng. Truy cập vào link, sử dụng dev tool của trình duyệt để kiểm tra các phần tử của website. Chúng ta có một số kết luận như sau:
Lưu ý rằng cấu trúc HTML trên có thể đã thay đổi so với thời điểm bài viết được tạo ra, vì vậy, bạn nên tự mình vào link và tìm tòi. Đây có lẽ là công đoạn thú vị nhất trong toàn bộ quá trình. Request đến websiteSử dụng Goutte\Client, ta có thể request đến web bằng url của nó và nhận lại một đối tượng thuộc kiểu 1.
Trích xuất dữ liệuVới đối tượng $crawler trong tay, để lấy ra thông tin từ website ta viết tiếp hàm scrape với đoạn code sau: 0Mỗi đôí tượng thuộc Crawler đại diện cho một đối tượng trên website. Ở trong hàm scrape() của chúng ta, $crawler đại diện cho toàn bộ trong web. Hàm filter() chỉ có tác dụng trong phạm vi mà Cralwer đại diện. Nó nhận vào một đoạn CSS selector và trả về một hoặc một danh sách các Crawler ứng với. Ta tiếp tục chain hàm each() vào sau filter. Hàm này nhận vào một Clouse, mang Closure này áp dụng lên từng phần tử trong danh sách mà filter() trả về trước đó. Đối số của Clouse chính là mỗi phần tử trong danh sách. Ở đây, $node đại diện cho HTML element ứng với mỗi sản phẩm. Bên trong hàm each, ta dễ dàng trích xuất ra thông tin tên sản phẩm, giá và số sao đánh giá dựa theo CSS selector của nó. Với rating, ta sử dụng hàm count() để đếm số sao mỗi loại và cộng nó vào giá trị cuối cùng. Lưu ý $price nhận về là một chuỗi có dạng 2. Để chuyển nó về dạng số cần sử dụng một chút regex, như đã được giới thiệu trong bài viết trước. 1Công việc còn lại đơn giản là lưu lại thông tin vào DB 2Dùng Artisan Console để chạy Web ScraperVì việc scraper có thể diễn ra trong một thời gian rất dài, không thể nào gọi hàm scrape() vừa viết ở trên trong controller và request tới app để khởi chạy scraper được. Trong ứng dụng thực thế, việc chạy scraper có thể được tạo bằng việc sử dụng cron job. Tuy nhiên, ở ứng đơn giản này, ta sẽ viết một Command và chạy scraper bằng terminal. Từ terminal, chạy lệnh: 3Một file ScraperCommand.php sẽ được tạo tại thư mục App/Console/Command. Bạn cần điều chỉnh giá trị biên signature lại như sau, với 3 chính là lệnh mình sẽ chạy trên terminal sau này. 4Sau đó sửa nội dung của hàm handle như sau 5Nếu chạy lệnh 4 mà nhìn thấy scrape:tgdd ở trong danh sách thì việc tạo Command đã thành công.Kết quảSau khi đã hoàn tất mọi bước trên, bạn có thể tận hưởng thành quả bằng cách chạy lệnh artisan do chính mình viết ra ở bước kế trước. Từ terminal, gõ: 6Kiểm tra database để thấy kết quả. Kết luậnViệc xây dựng web scraper trở nên cực kì đơn giản với Goutte. Bạn có thể tham khảo thêm về Goutte và DomCralwer theo các link bên dưới: Goutte: https://github.com/FriendsOfPHP/Goutte DomCralwer: https://symfony.com/doc/current/components/dom_crawler.html Tuy nhiên, hạn chế của Goutte (và tất cả headless browser nói chung) là các button sử dụng AJAX. Tại thời điểm viết bài này, ở cuối trang web thế giới di động có một button, khi click vào sẽ trigger một hàm Javascript để load thêm sản phẩm. Sử dụng Goutte không thể mô phỏng lại hành động này, vì vậy chỉ có thể scrape được 28 sản phẩm ở trang đầu. Để xử lí vấn đề này, cần dùng một browser simulator như puppeteer của Javascript. Nội dung về puppeteer có thể sẽ được thảo luận ở một bài viết trong tương lai. Xin cảm ơn. |