评论数据采集方法

  打开进入视频详情页面  

     作品详情链接格式  https://www.youtube.com/watch?v={作品id}

  控制台中解析需要的请求数据 以及参数加密的分析
  1.  接口地址 https://www.youtube.com/youtubei/v1/next?prettyPrint=false
  2.  请求方式为 POST
  3.  请求头需要携带 Referer(页面地址) 页面cookie 最好携带上固定就可以 
  4.  请求体参数主要为 context.client 跟 continuation (youtube加密的参数)

简单分析下 continuation 这个参数 示例 Eg0SC2JxSndMNHpwd3J3GAYyJSIRIgticUp3TDR6cHdydzAAeAJCEGNvbW1lbnRzLXNlY3Rpb24%3D,我这边经过尝试是先进行url 解码, 然后再进行base64解码能看到一点需要的参数

能看到携带了视频的id, 然后跟 comments-section这个参数,然后这些空白的就是一些二进制数据,需要在浏览器能显示但是我没看懂。但是通过替换视频id,换成我们需要的,然后进行base64 等加密,发现放接口里也可以用,但是只能查看一页的评论的数据,想看全部得需要完全破解这个参数,有大佬能通过逆向出来这个参数分享下

获取视频下的评论数据。以下是一个PHP调用示例:

  代码需要优化一下,根据业务

<?php

class Youtube {

    const API = 'https://www.youtube.com';
    const COMMENT_URL = '/youtubei/v1/next';

    /**
     * 公共 CLIENT 请求参数
     */
    const DEFAULT_CLIENT_CONFIG = [
        "hl" => "zh-CN",
        "gl" => "US",
        "deviceMake" => "Apple",
        "deviceModel" => "",
        "userAgent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36,gzip(gfe)",
        "clientName" => "WEB",
        "clientVersion" => "2.20251102.09.00",
        "osName" => "Macintosh",
        "osVersion" => "10_15_7",
        "screenPixelDensity" => 2,
        "platform" => "DESKTOP",
        "clientFormFactor" => "UNKNOWN_FORM_FACTOR",
        "screenDensityFloat" => 2,
        "userInterfaceTheme" => "USER_INTERFACE_THEME_DARK",
        "timeZone" => "Asia/Shanghai",
        "browserName" => "Chrome",
        "browserVersion" => "142.0.0.0",
        "memoryTotalKbytes" => "8000000",
        "acceptHeader" => "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
    ];

    protected $commonHeader;
    public $cookie = null;


    public function __construct($options = [])
    {
        $this->commonHeader = $this->getCommonHeader();
        $this->cookie = $this->getDefaultCookies();
        if (isset($options['cookie'])) {
            $this->cookie = $options['cookie'];
        }
    }


    /**
     * 公共headers
     * @return string[]
     */
    public function getCommonHeader(): array
    {
        return [
            'Content-Type: application/json',
            'Authorization: SAPISIDHASH 1762228162_6381649b2de5c245cd744c6cca862c92d88aa804_u SAPISID1PHASH 1762228162_6381649b2de5c245cd744c6cca862c92d88aa804_u SAPISID3PHASH 1762228162_6381649b2de5c245cd744c6cca862c92d88aa804_u',
            'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36'
        ];
    }

    /**
     * 默认cookie
     * @return string
     */
    public function getDefaultCookies(): string
    {
        return "VISITOR_INFO1_LIVE=0naC1y6HQgA; VISITOR_PRIVACY_METADATA=CgJVUxIEGgAgUA%3D%3D; HSID=AexUXBUZbpVBdv9nf....";
    }


    /**
     * 获取评论
     */
    public function getCommentList($videoId, $extend = [])
    {
        $apiUrl = self::API . self::COMMENT_URL . '?' . 'prettyPrint=false';
        $client = array_merge(self::DEFAULT_CLIENT_CONFIG,[
            "gl" => "TW",
            "remoteHost" => "36.231.173.75",
            "visitorData" => "CgswbmFDMXk2SFFnQSjC0KbIBjIKCgJVUxIEGgAgUA%3D%3D",
            "originalUrl" => "https://www.youtube.com/watch?v=" . $videoId,
            "deviceExperimentId" => "ChxOelUyT0RjMk5UWTFNakF5TlRrd09Ea3pNQT09EMLQpsgGGMLQpsgG",
            "rolloutToken" => "CL_QjIOqlZeOhgEQ9Mq5gvP0jQMYjtTfkMHXkAM%3D",
            "screenWidthPoints" => 1176,
            "screenHeightPoints" => 832,
            "utcOffsetMinutes" => 480,
            "connectionType" => "CONN_CELLULAR_3G",
            "configInfo" => [
                "appInstallData" => "CMLQpsgGEK7WzxwQzN+uBRCU/rAFEIKU0BwQlIPQHBC35M8cEL6KsAUQjcywBRC9mbAFEKaasAUQ0+GvBRDevM4cELOQzxwQka+AE3kIATKMuRgBMotZuAEyiSo4ATKJalgBMovaaAEyiRr4ATKNiwgBMoxLGAEyjRsYATKOWygBMo87OAEyiTtIATKLy0gBMozrSAEyittYATKLi1gBMoxLaAEyiwt4ATKNu3gBMogriAEyj2uIATMjJBT2pGb3gxQXotY3ZuY1l1WjhZTUQzMTRnRkEzbDM2WVZKcEhSR3VTeUhLbkNsdV83QToyQU9qRm94MWcwRkYwMVpOaVlQWTMydUliaDhsbG14Z1VJU1FFT3Q4OEw5dDhkYzFGTFFCNENBTVNJZzBLb3RmNkZhN0JCcE5Oc3hiTVJ4VVczY19DRE5Qb0QtdTM1Z3ZZelFuemtBUT0%3D"
            ],
            "mainAppWebInfo" => [
                "graftUrl" => "https://www.youtube.com/watch?v=" . $videoId,
                "pwaInstallabilityStatus" => "PWA_INSTALLABILITY_STATUS_UNKNOWN",
                "webDisplayMode" => "WEB_DISPLAY_MODE_FULLSCREEN",
                "isWebNativeShareAvailable" => true
            ]
        ]);


        $body = [
            'context' => [
                'client' => $client,
            ],
            'continuation' => self::encodeCommentParams($videoId)
        ];

        $postData = json_encode($body, JSON_UNESCAPED_SLASHES);
        $this->commonHeader[] = 'Referer: '. self::API .'/watch?v='. $videoId;
        return $this->extracted($apiUrl, $postData, $this->commonHeader, [
            'cookies' => $this->cookie,
        ]);
    }

    /**
     * 接口请求
     * @param $postData
     * @param string $apiUrl
     * @param $cookie
     * @return bool|string
     */
    private function extracted(string $apiUrl,$postData, $headers, $extend = [])
    {
        $this->commonHeader[] = 'Content-Length: ' . strlen($postData);

        $req = curl_init($apiUrl);
        curl_setopt($req, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($req, CURLOPT_POST, true);
        if (isset($extend['cookies'])) {
            curl_setopt($req, CURLOPT_COOKIE, $extend['cookies']);
        }
        curl_setopt($req, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($req, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($req);
        curl_close($req);

        return $response;
    }

}


$ytb = new Youtube();

/**
 * 评论数据调用及解析
 * @param $videoId
 * @param $extend
 * @return array
 */
function ytbComment($videoId, $extend = [])
{
    global $ytb;
    $commentResponse = $ytb->getCommentList($videoId, $extend);

    $commentArray = json_decode($commentResponse, true);

    $mutationsList = $commentArray['frameworkUpdates']['entityBatchUpdate']['mutations'];

    $commentList = [];

    foreach ($mutationsList as $mutation) {
        if (isset($mutation['payload']['commentEntityPayload']['properties']['content'])) {
            $properties = $mutation['payload']['commentEntityPayload']['properties'];
            $commentList[] = [
                'text' => $properties['content']['content'],
                'authorButtonA11y' => $properties['authorButtonA11y'],
                'commentId' => $properties['commentId'],
                'publishedTime' => $properties['publishedTime'],
            ];
        }
    }
    return $commentList;
}


$comment = ytbComment("2KBjtrfaZzE");
echo json_encode($comment, JSON_UNESCAPED_SLASHES);
  打印调用结果 ​   

注意事项

  1. 接口调用规范
    • 需要定期更新 Cookie
    • 适当增加请求间隔
    • 使用代理提高稳定性
  2. continuation 参数
    • 需要使用 JavaScript 计算签名
    • 逆向获取请求参数加密的方法
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐