YouTube时间轴热力图数据获取分析
随便打开一个视频在空白处点鼠标右键然后点开检查。
然后点开网络刷新页面:
刷新完发现有好多请求的数据:
这些就是构成该网页的所有数据,这些数据就是从服务器传输到我们本机的吗,传输的这些就是构建该网页所有需要用的的数据,包括源码,视频,音频,代码等。
我们需要找到时间轴热力图肯定也在里面,所以我们现在耐心寻找即可
tips:
网络传输的数据有明文和密文,明文就是我们能直接看到的,没有经过加密的;
密文就是经过各种加密后传输的,比如RSA加密,AES加密等,经过观察,我们需要的时间轴热力图是明文,所以不需要解密。
如何解密加密的数据在这里不详细讲解了,有需要后面再说。
凭借我的经验,时间轴热力图肯定是是列表的格式:[{},{},{},{}],该格式方便记录一些东西,组成这个数据根据经验肯定需要时间和热力值,所以我们可以从这点下手,寻找该格式的列表。
根据经验,这种格式的数据一般就是json,所以我们可以先从Fetch/XHR里寻找。
我的具体分析过程就不展开讲解了,结论就是不在Fetch/XHR里面,而是在这个里面:
这个是html文件,这个文件里的script标签下就有json格式的数据,但是这个文件也太大了,好多字符。
一开始我也是凭感觉,觉得这里也有可能有,就耐心翻了翻,没想到翻到了最下面才找到/(ㄒoㄒ)/~~
就是下面这个东西:
这个组成的结构和一开始猜想的差不多,有开始时间和值,这个热力值是从0到1,0是最低,1是最高。
找到该数据后就可以写代码来获取这个值了;
由于没有加密,也不需要cookie,可以直接获取。
代码在下面:
import requests
from bs4 import BeautifulSoup
import json
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import pandas as pd
while True:
link = input('请输入视频链接来获取:')
ids = link.split('v=')[1]
headers = {
'accept': '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',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
'cache-control': 'no-cache',
'pragma': 'no-cache',
'priority': 'u=0, i',
'sec-ch-ua': '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
'sec-ch-ua-arch': '"x86"',
'sec-ch-ua-bitness': '"64"',
'sec-ch-ua-form-factors': '"Desktop"',
'sec-ch-ua-full-version': '"131.0.6778.109"',
'sec-ch-ua-full-version-list': '"Google Chrome";v="131.0.6778.109", "Chromium";v="131.0.6778.109", "Not_A Brand";v="24.0.0.0"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-model': '""',
'sec-ch-ua-platform': '"Windows"',
'sec-ch-ua-platform-version': '"19.0.0"',
'sec-ch-ua-wow64': '?0',
'sec-fetch-dest': 'document',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'same-origin',
'sec-fetch-user': '?1',
'service-worker-navigation-preload': 'true',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
'x-browser-channel': 'stable',
'x-browser-copyright': 'Copyright 2024 Google LLC. All rights reserved.',
'x-browser-validation': 'Nbt54E7jcg8lQ4EExJrU2ugNG6o=',
'x-browser-year': '2024',
}
response = requests.get(link, headers=headers).text
soup = BeautifulSoup(response, 'html.parser')
for i in soup.select('script'):
if 'markersList' in str(i):
datadata = i.text.replace('var ytInitialData = ', '')[:-1]
datadata = json.loads(datadata)
data = datadata["frameworkUpdates"]["entityBatchUpdate"]["mutations"][0]["payload"]["macroMarkersListEntity"]["markersList"]["markers"]
toexceldata = pd.DataFrame(data)
toexceldata.to_excel(f'HeatmapIntensityOverTime - {ids}.xlsx', index=False)
# 提取时间和强度分数
start_times = [int(item["startMillis"]) for item in data]
durations = [int(item["durationMillis"]) for item in data]
intensity_scores = [float(item["intensityScoreNormalized"]) for item in data]
# 计算每个时间段的结束时间
end_times = [start + duration for start, duration in zip(start_times, durations)]
# 绘制热度线
plt.figure(figsize=(20, 2)) # 设置图像的长高比为20:10
plt.plot(start_times, intensity_scores, marker='o', linestyle='-', color='b')
# 设置坐标轴标签
plt.xlabel('Time (minutes:seconds)')
plt.ylabel('Normalized Intensity Score')
plt.title('Heatmap Intensity Over Time')
# 自定义X轴刻度格式化
def format_time(x, pos):
minutes = int(x // 60000)
seconds = int((x % 60000) // 1000)
return f"{minutes}:{seconds:02d}"
# 应用自定义刻度格式化
plt.gca().xaxis.set_major_formatter(ticker.FuncFormatter(format_time))
# 显示图形
plt.savefig(f'HeatmapIntensityOverTime - {ids}.png')
plt.show()
print('表格已保存,图片已保存!')
评论列表
${content}