
在数据采集与内容分析的实际工作中YouTube 评论区往往是最有价值、也最难拿到的数据源之一。本文围绕「如何采集 YouTube 视频下的评论数据」这一具体问题展开从进入视频详情页、在浏览器控制台中定位真实请求接口到分析continuation参数的编码方式再到用 PHP 编写可运行的调用示例并解析返回结果完整走一遍从抓包到落地的流程。本文适合具备一定后端开发基础、熟悉 HTTP 请求与 JSON 解析并且对接口逆向和参数分析有兴趣的读者例如做数据采集、内容分析、舆情监控或爬虫工程的同学。阅读完本文你将能够理解 YouTube 评论接口的请求结构与关键参数掌握continuation参数的初步解码思路拿到一份可直接参考的 PHP 采集代码并清楚在实际使用中需要注意的 Cookie 更新、请求频率与代理稳定性等问题。目录评论数据采集方法打开进入视频详情页面控制台中解析需要的请求数据以及参数加密的分析获取视频下的评论数据PHP 调用示例打印调用结果注意事项评论数据采集方法打开进入视频详情页面作品详情链接格式https://www.youtube.com/watch?v{作品id}控制台中解析需要的请求数据以及参数加密的分析接口地址https://www.youtube.com/youtubei/v1/next?prettyPrintfalse请求方式为 POST请求头需要携带 Referer页面地址和页面 Cookie最好固定携带即可请求体参数主要为 context.client 和continuationYouTube 加密的参数简单分析一下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/xhtmlxml,application/xml;q0.9,image/avif,image/webp,image/apng,/*;q0.8,application/signed-exchange;vb3;q0.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_LIVE0naC1y6HQgA; VISITOR_PRIVACY_METADATACgJVUxIEGgAgUA%3D%3D; HSIDAexUXBUZbpVBdv9nf....; } /** 获取评论 */ public function getCommentList($videoId, $extend []) { $apiUrl self::API . self::COMMENT_URL . ? . prettyPrintfalse; $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 CMLQpsgGEK7WzxwQzNuBRCU/rAFEIKU0BwQlIPQHBC35M8cEL6KsAUQjcywBRC9mbAFEKaasAUQ0GvBRDevM4cELOQzxwQkaAE3kIATKMuRgBMotZuAEyiSo4ATKJalgBMovaaAEyiRr4ATKNiwgBMoxLGAEyjRsYATKOWygBMo87OAEyiTtIATKLy0gBMozrSAEyittYATKLi1gBMoxLaAEyiwt4ATKNu3gBMogriAEyj2uIATMjJBT2pGb3gxQXotY3ZuY1l1WjhZTUQzMTRnRkEzbDM2WVZKcEhSR3VTeUhLbkNsdV83QToyQU9qRm94MWcwRkYwMVpOaVlQWTMydUliaDhsbG14Z1VJU1FFT3Q4OEw5dDhkYzFGTFFCNENBTVNJZzBLb3RmNkZhN0JCcE5Oc3hiTVJ4VVczY19DRE5Qb0QtdTM1Z3ZZelFuemtBUT0%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);打印调用结果注意事项接口调用规范需要定期更新 Cookie适当增加请求间隔使用代理提高稳定性continuation 参数需要使用 JavaScript 计算签名逆向获取请求参数加密的方法