Crawl dữ liệu trên trang chuyencuadev.com

5298

Bài viết của tác giả Lực Dương đăng trên Blog.techtalk

Vô tình biết được chuyencuadev.com. Mình liền nảy sinh ý định xấu xa, lấy toàn bộ dữ liệu mang về nhà cất:)

Dữ liệu thì cũng không có gì ngoài danh sách các công ty IT ở VN (Khoảng ~ 3400). 🙂

Mình cũng chẳng biết lấy về làm gì nữa. Chắc là để build một cái tương tự. =))

Chuẩn bị

Để lấy được thì cũng phải chuẩn bị một vài cái trước khi lấy chứ nhỉ.

1. Yêu cầu

Yêu cầu thì đơn giản rồi. Lấy danh sách 3491 công ty từ trang chuyencuadev

2. Kiểm tra hàng họ

Check một hồi chả biết là họ đang dùng cái quỉ gì để làm được cái web này nữa. =))

Cơ mà thấy một nút Xem thêm to bự chảng gần cuối trang. Mừng thấy mẹ. Nhấn thử xem nó có cái gì.

Buồn thối ruột vì họ dùng server render, không phải XHR request. Vậy là không vui rồi. Vì lúc này mình chẳng chôm chỉa được dữ liệu có cấu trúc dạng JSON hoặc XML gì đó.

Lúc này mình phải nghĩ đến việc parse html rồi. Nhìn quanh quẩn thì thấy trên domain có cái /page/2.

Ồ. Có thể dùng được rồi. Bắt tay vào làm thôi.

3. Lựa chọn công cụ, ngôn ngữ.

python hoặc nodejs

Mình khoái nodejs hơn nên quyết định chọn nodejs cho game này.

Phân tích

Cấu trúc

Chẳng biết cấu trúc của cái nồi này ra sao, nên phải mò một lúc. Mình thấy họ phân trang, mỗi trang có n công ty. Mà cụ thể là:

À, có cái list-companies và trong đó có nhiều items tile. Hehe Bao nhiêu item đây.

-> Có 3491 / 20 ~ 175 pages Chốt hạ có 175 pages cần khai thác.

Tức là mình sẽ có một vòng for chạy từ 0 đến 174 và parse dữ liệu.

Tạm dừng ở đây đã.

Phân tích sâu hơn.

Mình có 175 lần lặp, mỗi lần sẽ parse data để lấy dữ liệu. Vậy thì hàm parse đó sẽ làm gì?

  • Get html từ https://chuyencuadev.com/page/${i}
  • Dùng DOM Parser hoặc cái gì đó giống jQuery để có thể động đến các thẻ html một cách nhanh nhất. Để đó, search sau.
  • Xác định đối tượng list-companies
  • Define Company Object (Sau khi đã xác định được các thành phần của một đối tượng)

Chết cha. Toàn bộ chỉ có thế. Code thôi.

Code

Create Project

Packages

yarn add mongoose connect-mongo moment lodash request request-promise cheerio

Một vài thư viện mà mình nghĩ là mình sẽ dùng. Cơ mà chắc chỉ dùng mongoose, connect-mongo, request-promise, cheerio thôi. Còn moment và lodash thì mình chưa biết sẽ làm gì với nó. Cơ mà trong đầu nghĩ là sẽ dùng. =))

cheerio => jQuery basic for nodejs.

index.js

Thử code cái đã. 😀

Well done! Ta có output ưng ý.

hmmm… Cùng thử lấy ra list-companies như mình mô tả ở trên nào.

-> Tuyệt cú mèo. Mọi thứ đúng như những gì mình làm với jQuery trên client. 🙂 Vậy thì cứ thế mà chiến tiếp thôi.

Mình sẽ tiến hành parse list of companies

Còn đây là parse từng company Object

Và response theo ý muốn…

Cũng gọi là chim ưng với kết quả này. Mình bắt tay làm tới. Quất thẳng 172 cái pages và lưu vào trong mongo-db

Define DB & Schema

Mình hơi màu mè tẹo. Tạo hẳn cái Schema cho nó vui. models/Company.js

Và đúng thủ tụ.

Kết quả có vẻ không đẹp cho lắm khi một số request bị timeout. :(. Mỗi lần như vậy mình lại phải chạy lại từ đầu thì không ổn. Mình quyết định viết một recursive function. Hi vọng sẽ chạy những cái page nào bị timeout trước đó.

Cái hàm đó nhìn như thế này.

Kết quả

Chả được cái tích sự gì khi mà server bên đó hơi cùi tí tẹo. Mới chạy có mấy chục cái request liên tục mà tải không nổi. Bị request timeout, nhảy vô web của họ thì thấy bị hi sinh luôn.

Kiến thức đã dùng

  • nodejs ES6 (Node v8)
  • async/await
  • Promise

Source Code

git@github.com:lucduong/crawl-companies.git

https://github.com/lucduong/crawl-companies

Kết luận.

Thôi dẹp, lấy được đến đâu lấy. =)).

Đùa vậy thôi, mình có sửa lại chỗ này tí Company.create(companies) thành createCompanies(companies) và trong hàm createCompanies mình findOneAndUpdate để sau này stop, start lại nó ko update trùng.

Đúng ra còn nhiều cách tối ưu khác nữa nhưng mình xin phép nhường lại cho bạn đọc. Và hi vọng các bạn sẽ contribute thêm.

Có thể là mình sẽ đánh dấu lại những trang nào đã lấy dữ liệu rồi và loại trừ, lần sau chạy lại sẽ ko lấy nữa. Các bạn làm giúp mình với nhé. 😀

Techtalk via Blog.techtalk

CHIA SẺ