Thử crawl data trên viblo
This post hasn't been updated for 4 years
Trước tiên truy cập trang chủ truy cập tab newest https://viblo.asia/newest
Có nhiều cách để crawl data có thể dùng, sau đây mình giới thiệu 2 cách mình đã sử dụng
Cách 1
bạn kéo xuống cuối trang và click vào page 2 mục địch là kiếm api gọi khi chuyển trang!
F12 lên kiếm api nào filter với từ khóa new
nó đây https://viblo.asia/api/posts/newest?page=2&limit=20
trong url ta thấy có limit kìa :v
thử limit vs 30 xem https://viblo.asia/api/posts/newest?page=2&limit=30
ngon.. ra 30 luôn
thử tip 60 coi nà
đìu.. ra luôn (ngon)
lướt lên lại đầu trang ta thấy viblo có ~1200 trang thử với 1000x20 =20000 limit xem nà (mặc định paging của viblo là 20) có khi chỉ cần 1 api là có hết data của viblo
đìu méo được.. api đã giới hạn max là 100 rồi
công việc tiếp theo là viết code loop call tới api để lấy data về dùng thôi =))
Cách 2
Cách này chủ yếu là để nghiên cứu thêm cách sử dụng puppeteer, tài liệu của nó đây puppeteer mô tả ngắn gọn về nó thì nó giúp chúng ta tương tác với browser mà ko cần giao diện
Nhiệm vụ chính của chúng ta thì chỉ cần như thế này thôi:
Step 1: Truy cập url
Step 2: Crawl dữ liệu
Step 3: Chuyển trang
Step 4: Crawl dữ liệu
Step 5: Chuyển trang
loop tới khi nào hết thì thôi :v
Băt đầu như lúc truy cập vào browser ta cần địa chỉ của url cần đến
Thông thường thì muốn https://viblo.asia/newest
Convert qua puppeteer thôi:
Giả lập trình duyệt thôi tạo browser trong browser tạo new tab (page) :v
const browser = await pt.launch({
headless: false,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
const page = await browser.newPage();
Step 1: Truy cập url
await page.goto('https://viblo.asia/'newest ',{waitUntil: 'load'});
waitUntil load => có nghĩa là truy cập trang và chờ tời khi trang load xong rồi mới xử lí tiếp
bình thường thì chỉ cần check api và lấy dữ liệu về thôi.. nhưng ko mình muốn sử dụng puppeteer để đọc html và lấy thông tin từ đó.. ta cùng xem cấu trúc nội dung list post của viblo:
bây giờ mình muốn lấy cái slug của bài viết(aWj53Dd1K6m) thì nó nằm ở thẻ a trong thuộc tính href... Vậy làm cách nào để lấy được giá trị đó, minh nghĩ tới dùng javascript đầu tiên
Và để dùng javascript trong puppeteer ta sử dụng api evaluate()
articles = await page.evaluate(() => {
let imgElements = document.querySelectorAll('.post-title--inline h3 a');
imgElements = [...imgElements];
let articles = imgElements.map(i => {
return i.getAttribute('href').split('-').pop();
});
return articles;
});
đọc sơ qua thì ta có thể hiểu là lấy 1 list thẻ a.. loop lấy từng cái lấy thuộc tính href cắt nhỏ thông qua dấu '-' sau đó lấy phần tử cuối
Kết quả cuối cùng ta được mảng slug của danh sánh bài post ở trang hiện tại => ta lưu vào ở đâu đó để sử dụng.. lưu ở file.. ở database
Vậy lấy thêm 1 rồi thi làm gì tiếp ae.. tất nhiên là chuyển qua trang khác để lấy tiếp dữ liệu.. cho nên ta nên vứt đoạn code trên trong vòng lặp.. ta lấy 500 trang thôi nha
for (var i = 2; i < 500; i++) {
articleIds = await page.evaluate(() => {
let imgElements = document.querySelectorAll('.post-title--inline h3 a');
imgElements = [...imgElements];
let articleIds = imgElements.map(i => {
return i.getAttribute('href').split('-').pop();
});
return articleIds;
});
//TODO save
}
Chừng đó là chưa đủ ta viết thêm đoạn code cho nó chuyển trang nữa nhé:
Kéo xuống f12 chỗ cái page để kiếm cái link nà
code code code...
for (var i = 2; i < 500; i++) {
articleIds = await page.evaluate(() => {
let imgElements = document.querySelectorAll('.post-title--inline h3 a');
imgElements = [...imgElements];
let articleIds = imgElements.map(i => {
return i.getAttribute('href').split('-').pop();
});
return articleIds;
});
//TODO save
navigationPromise = page.waitForNavigation();
await page.click('.pagination a[href*="/?page='+i+'"]');
await navigationPromise;
}
waitForNavigation() : đại loại như là chờ tới khi trang chuyển trang xong
page.click(selector[, options]) : phát sinh sự kiện click cho selector truyền vào document ở đây nhé
Rất đơn giản phải không các bạn ta có crawl data với bất kì trang web nào.. bằng cách kết hợp sử dụng puppeteer ta có thể lấy được những thông tin mà api ko trả về luôn
Bonus thêm api lấy post chi tiết 'https://viblo.asia/api/posts/' + slugPost
All Rights Reserved