I/ Yêu cầu:
- Từ 1 channel tiktok lấy toàn bộ thông tin tất cả videos của channel, xuất ra file (excel, text...)
II/ Phân tích
- Ban đầu mình cũng thử 1 vài cách như dựng 1 server nodejs, expose 1 api nhận vào tham số là url channel (vd: https://www.tiktok.com/@lingg2809 ) rồi dùng các libs như puppeteer để crawl dữ liệu channel, từ đó lấy ra danh sách url video của channel. Từ danh sách đó, call tiếp để lấy các thông tin của video tương ứng. Cách này hoạt động, nhưng khi deploy lên vercel bị giới hạn (vượt quá 50mb) vả lại khách hàng cần 1 tool đơn giản không phải triển khai lằng nhằng, nên chuyển sang viết extension cho chrome chạy cho đơn giản
- Tham khảo từ một số tool đã có, chọn hướng xử lý là khi extension hoạt động.
- Sẽ tự động scoll xuống cuối trang dần dần cho tới khi chạm vào cuối trang, mục đích là để tiktok load hết danh sách videos của channel. Do tiktok dùng kiểu lazyload để hiển thị danh sách video, có rủi ro là scroll quá nhanh hoặc api xử lý châm, dẫn tới load thiếu => có thể khắc phục bằng cách tăng thời gian timeout giữa các lần scroll, nhược là thời gian bước này sẽ lâu hơn và vẫn có rủi ro api chậm
- Lấy tất cả url videos trong trang, với mỗi url video sẽ call thêm 1 lần nữa để lấy html trang video. Từ response trả về trích xuất ra thông tin cần thiết và đẩy vào file tương ứng
III/ Tiến hành
1/ Tạo file manifest.json (xem thêm ở đây: https://developer.chrome.com/docs/extensions/mv3/manifest/) > thêm matches để extends chỉ xuất hiện ở trang tiktok, xlsx để xuất ra file excel. index.js là file chương trình chính của chúng ta
{ "manifest_version": 3, "name": "Get tiktok videos info", "version": "1.0", "description": "Get tiktok videos info", "icons": { "16": "images/icon-16.png", "32": "images/icon-32.png", "48": "images/icon-48.png", "128": "images/icon-128.png" }, "content_scripts": [ { "js": [ "scripts/xlsx.full.min.js", "scripts/index.js" ], "matches": [ "https://www.tiktok.com/*" ] } ]
}
2/ index.js
- Tạo 1 nút để kích hoạt sự kiện bắt đầu thu thập dữ liệu
if (!document.getElementById(CONFIG.EXPORT_ID)) { const exportBtn = document.createElement("button"); exportBtn.innerText = "Export data"; exportBtn.setAttribute( "style", "background-color: #f72247a3;color: white;position: fixed;top: 150px;right: 25px;cursor: pointer;display: flex;justify-content: center;align-items: center;width: 4rem;height: 4rem;border-radius: 2rem;border: 1px solid;" ); exportBtn.setAttribute("id", CONFIG.EXPORT_ID); exportBtn.addEventListener("click", exportData); document.body.appendChild(exportBtn);
}
-
Bắt đầu thu thập dữ liệu
showLoadingView(); await scrollShowAllVideos(); const urls = getVideosUrl(); setLoadingProcess(
Xuất file excel...); const videos = await getVideosMeta(urls); exportToFile(videos); closeLoadingView();
-
Scroll xuống để lấy được hết videos `async function scrollShowAllVideos() { return new Promise((resolve) => { var totalHeight = 0; var distance = 100; var timer = setInterval(() => { var scrollHeight = document.body.scrollHeight; window.scrollBy(0, distance); totalHeight += distance;
if (totalHeight >= scrollHeight) { clearInterval(timer); resolve(null); }
}, CONFIG.TIME_INTERVAL); }); }`
-
Lấy danh sách videos trong trang, dùng css selector bên dưới ta sẽ có được danh sác url của video
[data-e2e="user-post-item-list"] [data-e2e="user-post-item-desc"] a[href^="${location.href}"]
- Với từng url video, ta sẽ có được file html - tương ứng của trang video đó (dùng fetch(url)). Response xử lý dưới dạng text, với text html này ta có thể dùng DOMParser (https://developer.mozilla.org/en-US/docs/Web/API/DOMParser) rồi dùng css selector tương ứng với từng thông tin cần lấy. Vd: để lấy số lượng comment dùng '[data-e2e="comment-count"]', và lấy innerText của element
- Một cách xử lý khác là xử lý trực tiếp chuỗi string, do tiktok có lưu thông tin trong thẻ script id="SIGI_STATE". nên có thể trích xuất trực tiếp ra được, không cần DOMParser
- Sau khi có mảng thông tin các video tương ứng thì export ra file và lưu lại (ở đây mình dùng xlsx để export ra file excel) là xong
- Một trải nghiệm thú vị khi lần đầu viết extension , cảm ơn anh em đi trước
- video demo: https://drive.google.com/file/d/1KeZcEorx1RlxaR0BMoNolKvh6SugxceQ/view?usp=drive_link