我正在尝试制作一个工具,可以一次性下载 TikTok 上特定用户的每个视频。示例页面: https: //www.tiktok.com/@levelsofpiano。我首先检查了 TikTok 个人资料上的 html 树,其中显示了这些“a”标签,其中包含页面上加载的每个视频的视频页面链接。
我尝试使用wget来捕获页面,但是在生成的 html 中wget https://www.tiktok.com/@levelsofpiano > Output.html甚至没有提及。@levelsofpiano我猜网站上的内容是动态加载的,所以穷人wget得到的页面大部分是空的。
然后我决定使用testcafe(像 Selenium 这样的 UI 测试工具)加载页面,等待 20 秒,然后捕获 html 输出...但是当我使用此方法时,视频不会加载:

这是我的脚本:
import { Selector, ClientFunction } from 'testcafe';
import fs from 'fs';
let username = "levelsofpiano";
fixture `Get Dat Tiktok`.page("https://www.tiktok.com/@" + username);
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
/* got this definition from https://testcafe-discuss.devexpress.com/t/can-i-save-a-web-page-as-an-html-file/461 */
const getPageHTML = ClientFunction(() => document.documentElement.outerHTML);
test('Capture page with loaded elements', async t => {
await sleep(20000); //20 seconds
await fs.writeFile('./' + username + '.html',await getPageHTML(), function(err, result) {
if(err) console.log('error', err);
});
});
Run Code Online (Sandbox Code Playgroud)
我还能尝试什么来抓取所有这些视频?我可能需要一种方法来滚动页面来加载所有视频(我可以使用 testcafe 或 selenium 来完成。如果我能找到一种方法让它们加载我正在寻找的内容)
令人惊讶的是没有 API 来获取所有用户视频。我想出了这个 hacky 解决方案,它首先解析页面上已加载视频的 DOM,然后设置 XHR 覆盖来解析由自动滚动器触发的网络请求中的 JSON。将其粘贴到控制台后,您需要等待它运行(不要手动滚动),然后您可以登录allVideos查看视频 ID 数组。
或者,您可以只使用自动滚动功能并继续使用连续加载的视频解析 DOM。
window.allVideos = [];
getInitialVideoIDs();
const origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url) {
this.addEventListener('load', function() {
if (this.readyState === 4 && isVideoFetch(url)) {
const responseData = JSON.parse(this.responseText);
pushVideoIDs(responseData);
checkAutoScroller(responseData);
}
});
origOpen.apply(this, arguments);
};
const autoScroller = setInterval(function() {
window.scrollTo(0, document.body.scrollHeight);
}, 1000);
function isVideoFetch(url) {
const videoFetchRegEx = /\/api\/post\/item_list\//;
return videoFetchRegEx.test(url);
}
function pushVideoIDs(responseData) {
responseData.itemList.forEach(item => {
if (allVideos.indexOf(item.id) === -1) {
allVideos.push(item.id);
}
});
}
function checkAutoScroller(responseData) {
if (!responseData.hasMore) {
clearInterval(autoScroller);
}
}
function getInitialVideoIDs() {
const videos = document.querySelectorAll('.tt-feed .video-feed-item-wrapper');
videos.forEach(video => {
const urlObj = new URL(video.href);
const path = urlObj.pathname;
const id = (path.match(/\/video\/(\d+)/) || [])[1];
allVideos.push(id);
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5651 次 |
| 最近记录: |