【问题标题】:Scraping all videos from a tiktok profile从 tiktok 个人资料中抓取所有视频
【发布时间】:2020-04-28 15:19:57
【问题描述】:

我正在尝试制作一个工具,可以一次下载 TikTok 上给定用户的每个视频。示例页面:https://www.tiktok.com/@levelsofpiano。我首先检查了 TikTok 个人资料上的 html 树,它显示了这些“a”标签,其中包含指向页面上加载的每个视频的视频页面的链接。

我尝试使用wget 来捕获使用wget https://www.tiktok.com/@levelsofpiano > Output.html 的页面,但是在生成的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);
    });    
});

我还能尝试抓取所有这些视频吗?我可能还需要一种方法来滚动页面以加载所有视频(我可以使用 testcafe 或 selenium 来完成。如果我能找到一种方法让它们加载我正在寻找的内容)

【问题讨论】:

    标签: html web-scraping


    【解决方案1】:

    令人惊讶的是,没有用于获取所有用户视频的 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);
      });
    }
    

    【讨论】:

      猜你喜欢
      • 2021-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多