我只想获取所有我喜欢的视频~25k 个项目。据我的研究,这是不可能通过 YouTube v3 API 实现的。
我已经在同一个问题上发现了多个问题(问题,问题),尽管有些人声称已经修复了它,但它只适用于他们,因为他们没有< 5000 items in their liked video list.
播放列表 ID 设置为“喜欢的视频”(LL) 的playlistItems 列表 API 端点的限制为 5000。
视频列表 API 端点的限制为 1000。
不幸的是,这些端点没有向我提供可用于对请求进行分页的参数(例如,为我提供日期 x 和 y 之间所有喜欢的视频),因此我被迫接受所提供的订单(我可以这样做)没有超过 5000 个条目)。
我是否可以通过 API 获取我所有的点赞?
对@Yarin_007 的回复有更多想法
function collector(all_cards) {
var liked_videos = {};
all_cards.forEach(card => {
try {
// ignore Dislikes
if (card.innerText.split("\n")[1].startsWith("Liked")) {
....
}
}
catch {
console.log("error, prolly deleted video")
}
})
return liked_videos;
}
var millisecondsToWait = 1000;
setInterval(function() {
window.scrollTo(0, document.body.scrollHeight);
console.log("scrolling")
}, millisecondsToWait);
嗯。也许是Google Takeout?
我已验证 YouTube 数据包含一个名为“likedvideos.csv”的 csv。标题为
Video Id,Time Added
,行为
dQw4w9WgXcQ,2022-12-18 23:42:19 UTC
prvXCuEA1lw,2022-12-24 13:22:13 UTC
例如。
因此您需要检索每个视频 ID 的视频元数据。不过还不错。
注意: 导出可能需要一段时间,尤其是 25k 视频。 (仅选择 YouTube 数据)
我还有一个想法,涉及抓取实际喜欢的视频页面(这将为您节省 25k HTTP 请求)。但我不确定超过 5000 首歌曲是否会崩溃。 (此外,模拟该页面上的 POST 请求可能会相当困难,尽管并非不可能。(它们获取 /browse?key=...,并且在请求正文中具有某种模糊/加密的 base64 字符串以及其他参数) )
编辑:
看。可能有一种正常的方法可以完整转储所有谷歌数据。 (我的意思是,除了外卖。给他们发电子邮件?我不知道。) 无论如何,以下是另一个想法...
按照此深层链接查看您喜欢的视频历史记录。
滚动到底部...也许使用selenium,也许使用autoit,也许在键盘的“结束”键上放一些东西,直到到达第一个喜欢的视频。
按 f12 并在开发者控制台中运行它
// https://www.youtube.com/watch?v=eZPXmCIQW5M
// https://myactivity.google.com/page?utm_source=my-activity&hl=en&page=youtube_likes
// go over all "cards" in the activity webpage. (after scrolling down to the absolute bottom of it)
// create a dictionary - the key is the Video ID, the value is a list of the video's properties
function collector(all_cards) {
var liked_videos = {};
all_cards.forEach(card => {
// ignore Dislikes
if (card.innerText.split("\n")[1].startsWith("Liked")) {
// horrible parsing. your mileage may vary. I Tried to avoid using any gibberish class names.
let a_links = card.querySelectorAll("a")
let details = a_links[0];
let url = details.href.split("?v=")[1]
let video_length = a_links[3].innerText;
let time = a_links[2].parentElement.innerText.split(" • ")[0];
let title = details.innerText;
let date = card.closest("[data-date]").getAttribute("data-date")
liked_videos[url] = [title,video_length, date, time];
// console.log(title, video_length, date, time, url);
}
})
return liked_videos;
}
// https://stackoverflow.com/questions/57709550/how-to-download-text-from-javascript-variable-on-all-browsers
function download(filename, text, type = "text/plain") {
// Create an invisible A element
const a = document.createElement("a");
a.style.display = "none";
document.body.appendChild(a);
// Set the HREF to a Blob representation of the data to be downloaded
a.href = window.URL.createObjectURL(
new Blob([text], { type })
);
// Use download attribute to set set desired file name
a.setAttribute("download", filename);
// Trigger the download by simulating click
a.click();
// Cleanup
window.URL.revokeObjectURL(a.href);
document.body.removeChild(a);
}
function main() {
// gather relevant elements
var all_cards = document.querySelectorAll("div[aria-label='Card showing an activity from YouTube']")
var liked_videos = collector(all_cards)
// download json
download("liked_videos.json", JSON.stringify(liked_videos))
}
main()
基本上,它会收集所有喜欢的视频的详细信息,并为每个喜欢的视频创建一个
key: video_ID - Value: [title,video_length, date, time]
对象。
然后它会自动将 json 下载为文件。
能够获取喜欢、不喜欢以及次要标题(或副标题或副标题)的版本,后者有时很有用,因为对于音乐来说,如果艺术家姓名不在标题本身中而是在标题中,则可以帮助识别艺术家而是副标题或频道名称。当遇到无效的视频 ID(使用 URL 而不是视频 ID 标题)“www...”时,下面的材料会被破坏,但我可以使用帮助来解决这个问题...也许是受到开头的修复的启发这个线程。
function collector(all_cards) {
var videos = {};
all_cards.forEach(card => {
let action = card.innerText.split("\n")[1].split(" ")[0];
if (action === "Liked" || action === "Disliked") {
let a_links = card.querySelectorAll("a");
let details = a_links[0];
let url = details.href.split("?v=")[1];
let video_length = a_links[3].innerText;
let time = a_links[2].parentElement.innerText.split(" • ")[0];
let title = details.innerText;
let date = card.closest("[data-date]").getAttribute("data-date");
let secondary_headline = card.innerText.split("\n")[2].replace(/"/g, "");
videos[url] = [title, video_length, date, time, action, secondary_headline];
}
});
return videos;
}
// https://stackoverflow.com/questions/57709550/how-to-download-text-from-javascript-variable-on-all-browsers
function download(filename, text, type = "text/plain") {
// Create an invisible A element
const a = document.createElement("a");
a.style.display = "none";
document.body.appendChild(a);
// Set the HREF to a Blob representation of the data to be downloaded
a.href = window.URL.createObjectURL(
new Blob([text], { type })
);
// Use download attribute to set set desired file name
a.setAttribute("download", filename);
// Trigger the download by simulating click
a.click();
// Cleanup
window.URL.revokeObjectURL(a.href);
document.body.removeChild(a);
}
function main() {
// gather relevant elements
var all_cards = document.querySelectorAll("div[aria-label='Card showing an activity from YouTube']")
var liked_videos = collector(all_cards)
// download json
download("liked_videos.json", JSON.stringify(liked_videos))
}
main()