Skip to content

Instantly share code, notes, and snippets.

@kmorrill
Created November 21, 2024 15:59
Show Gist options
  • Save kmorrill/ae07179bea1a4f9b8c54db28b224c6cf to your computer and use it in GitHub Desktop.
Save kmorrill/ae07179bea1a4f9b8c54db28b224c6cf to your computer and use it in GitHub Desktop.
YouTube Like Scraping
(function() {
console.log('Script started.');
// Array to hold the CSV lines
let csvLines = [];
// Prepare the CSV header
csvLines.push('Title,URL,Channel Name,Upload Date,Duration,Thumbnail URL');
// Select all video elements inside the liked videos page
let videos = document.querySelectorAll('ytd-playlist-video-renderer');
// If no videos found, try an alternative selector
if (videos.length === 0) {
console.warn('No videos found with selector "ytd-playlist-video-renderer". Trying alternative selector.');
videos = document.querySelectorAll('ytd-grid-video-renderer');
}
console.log(`Found ${videos.length} video(s).`);
// Check if any videos were found
if (videos.length === 0) {
console.error('No videos found. Please ensure you are on your Liked Videos page and that the page has fully loaded.');
return;
}
// Iterate over each video element
videos.forEach((video, index) => {
console.log(`Processing video ${index + 1}...`);
// Extract the video title and URL
const titleElement = video.querySelector('#video-title');
const title = titleElement?.textContent.trim().replace(/"/g, '""') || '';
const url = titleElement?.href || '';
if (!titleElement) {
console.warn(`Title element not found for video ${index + 1}.`);
}
// Extract the channel name
const channelElement = video.querySelector('#channel-name a, #text-container a');
const channelName = channelElement?.textContent.trim().replace(/"/g, '""') || '';
if (!channelElement) {
console.warn(`Channel element not found for video ${index + 1}.`);
}
// Extract the upload date
const uploadDateElement = video.querySelector('#metadata-line span:last-child');
const uploadDate = uploadDateElement?.textContent.trim().replace(/"/g, '""') || '';
if (!uploadDateElement) {
console.warn(`Upload date element not found for video ${index + 1}.`);
}
// Extract the video duration
const durationElement = video.querySelector('ytd-thumbnail-overlay-time-status-renderer span, span.ytd-thumbnail-overlay-time-status-renderer');
const duration = durationElement?.textContent.trim().replace(/"/g, '""') || '';
if (!durationElement) {
console.warn(`Duration element not found for video ${index + 1}.`);
}
// Extract the thumbnail URL
const thumbnailElement = video.querySelector('img#img');
const thumbnailUrl = thumbnailElement?.src || thumbnailElement?.getAttribute('src') || '';
if (!thumbnailElement) {
console.warn(`Thumbnail element not found for video ${index + 1}.`);
}
// Log extracted data
console.log(`Video ${index + 1} data:`, {
title,
url,
channelName,
uploadDate,
duration,
thumbnailUrl
});
// Format each field to handle commas and quotes in CSV
const formattedTitle = `"${title}"`;
const formattedURL = `"${url}"`;
const formattedChannelName = `"${channelName}"`;
const formattedUploadDate = `"${uploadDate}"`;
const formattedDuration = `"${duration}"`;
const formattedThumbnailUrl = `"${thumbnailUrl}"`;
// Append the data row to the CSV content
csvLines.push(`${formattedTitle},${formattedURL},${formattedChannelName},${formattedUploadDate},${formattedDuration},${formattedThumbnailUrl}`);
});
// Combine the CSV lines into a single string
const csvContent = csvLines.join('\n');
// Replace the entire document content with the CSV data wrapped in a <pre> tag
document.open();
document.write('<pre>' + csvContent + '</pre>');
document.close();
console.log('Script finished. Page content replaced with CSV data.');
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment