PHP 抓取 Youtube视频评论获取方法
·
评论数据采集方法
打开进入视频详情页面
作品详情链接格式 https://www.youtube.com/watch?v={作品id}
控制台中解析需要的请求数据 以及参数加密的分析
- 接口地址 https://www.youtube.com/youtubei/v1/next?prettyPrint=false
- 请求方式为 POST
- 请求头需要携带 Referer(页面地址) 页面cookie 最好携带上固定就可以
- 请求体参数主要为 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);
打印调用结果
注意事项
-
接口调用规范
- 需要定期更新 Cookie
- 适当增加请求间隔
- 使用代理提高稳定性
-
continuation 参数
- 需要使用 JavaScript 计算签名
- 逆向获取请求参数加密的方法
更多推荐



所有评论(0)