Can't get a full playlist with pafy - python

I'm trying to get all the urls of the videos in a playlist.
The playlist contains 700+ videos.
When I create a playlist with pafy.get_playlist it only creates an array with 194 videos, not all of them.
So is there a size limit for the playlist with pafy?

According to this issue on their github page you can just use get_playlist2()

Hello Everyone this is my first answer:)
you can use get_playlist2() as #JalxP said
just checkout the below code and run it.
I think It should solve the problem
Thanks!
import pafy
import sys
import time
url = sys.argv[1] # takes the playlist link as argument
details = pafy.get_playlist(url)
playlist = pafy.get_playlist2(url)
# below three statements print the tilte,author and number of videos
print(details['title'])
print(details['author'])
print(len(playlist))
# path to store the videos
userpath = input("enter path to save the playlist:")
# you can modify this for loop for a particular range of videos
# this a bare-bone
# this loop downloads all the videos in the playlist
for item in range(len(playlist)):
url = playlist[item].getbest()
url.download(userpath)
time.sleep(3)# just to not make immediate download calls

import os
from pafy import get_playlist
import pafy
from pafy import *
from socket import *
name_pc=gethostname()
var2=name_pc.split("-")[0] # ex: ("document-PC") -> ["document","PC"]to get #name pc
os.chdir(r"C:\Users\\"+var2+"\\Downloads")
vobj=get_playlist(str(input("Enter a URL :")))
down_path=str(input("Enter a Dir ?: "))
for video in range(len(vobj['items'])):
down=vobj['items'][video]['pafy'].getbest() # to get all items for item in playlist
if 1:
t=r"C:\Users\\"+var2+"\\Downloads"
down.download(t)
else:
down.download(down_path)

Related

I need a way to pull 100 of the most popular channels and their ID's from YouTube using the youtube api in the python language

http://www.youtube.com/dev/ ive already checked the youtube api dev info and have not found anything pertaining to this.
Obtain API youtube
To be able to make requests of this type you must have an API key,
Go to link https://console.developers.google.com/
Create a new project
find youtube Data API v3 and click on it
Enable the API
go to credentials and create one for the project
write it down and insert it in the script below
This script uses ÁPI created previously to make requests on the channels by creating name in a random way and inserts the data in two files in the first it stores all the info in the second only the id, the channel name and the link to the channel, I hope it is what you are looking for ;)
import json
import urllib.request
import string
import random
channels_to_extract = 100
API_KEY = '' #your api key
while True:
random_name = ''.join(random.choice(string.ascii_uppercase) for _ in range(random.randint(3,10))) # for random name of channel to search
urlData = "https://www.googleapis.com/youtube/v3/search?key={}&maxResults={}&part=snippet&type=channel&q={}".format(API_KEY,channels_to_extract,random_name)
webURL = urllib.request.urlopen(urlData)
data = webURL.read()
encoding = webURL.info().get_content_charset('utf-8')
results = json.loads(data.decode(encoding))
results_id={}
if results['pageInfo']["totalResults"]>=channels_to_extract: # may return 0 result because is a random name
break # when find a result break
for result in results['items']:
results_id[result['id']['channelId']]=[result["snippet"]["title"],'https://www.youtube.com/channel/'+result['id']['channelId']] # get id and link of channel for all result
with open("all_info_channels.json","w") as f: # write all info result in a file json
json.dump(results,f,indent=4)
with open("only_id_channels.json","w") as f: # write only id of channels result in a file json
json.dump(results_id,f,indent=4)
for channelId in results_id.keys():
print('Link --> https://www.youtube.com/channel/'+channelId) # link at youtube channel for all result

How to add "pytube" downloading info to tqdm Progress Bar?

I am trying make a YouTube video downloader.
I want make a progress bar while downloading the YouTube video but I cant get any info (how many MB have been downloaded or how many video MB).
I don't know if this is possible with python or not. Here is my code so far:
import time , os
from pytube import YouTube
from tqdm import tqdm
al = str(input("C4ommand:"))
if al == "4":
af = input("Link:")
you = YouTube(af)
try:
os.mkdir("Download")
except:
pass
time.sleep(2)
time.sleep(1)
res = you.streams.get_highest_resolution()
a = res.download()
with tqdm(total=100) as pbar:
for i in range(10):
time.sleep(0.5)
pbar.update(10)
print(af + "Link downloading....")
b = open("\Download", "w")
b.write(a)
b.close()
print("Downloaded")
To access the progress of the download, you can use the on_progress_callback argument when creating a YouTube instance.
The pytube quickstart says the following:
The on_progress_callback function will run whenever a chunk is downloaded from a video, and is called with three arguments: the stream, the data chunk, and the bytes remaining in the video. This could be used, for example, to display a progress bar.
from pytube import Stream
from pytube import YouTube
from tqdm import tqdm
def progress_callback(stream: Stream, data_chunk: bytes, bytes_remaining: int) -> None:
pbar.update(len(data_chunk))
url = "http://youtube.com/watch?v=2lAe1cqCOXo"
yt = YouTube(url, on_progress_callback=progress_callback)
stream = yt.streams.get_highest_resolution()
print(f"Downloading video to '{stream.default_filename}'")
pbar = tqdm(total=stream.filesize, unit="bytes")
path = stream.download()
pbar.close()
print(f"Saved video to {path}")
Sample output:
Downloading video to 'YouTube Rewind 2019 For the Record YouTubeRewind.mp4'
100%|██████████████████████████████| 87993287/87993287 [00:17<00:00, 4976219.51bytes/s]
Saved video to /tmp/testing/YouTube Rewind 2019 For the Record YouTubeRewind.mp4
Pytube has a built-in progress bar, but it does not use tqdm. Please see https://stackoverflow.com/a/60678355/5666087 for more information.

Detect the end of a song using Spotipy

I'm using Spotipy and LyricsGenius to open lyrics on a web browser from a terminal.
I can open a url for one song, but have to run the script each time to run consecutively. What are some ways to detect the end of a song using Spotipy?
import spotipy
import webbrowser
import lyricsgenius as lg
...
# Create our spotifyObject
spotifyObject = spotipy.Spotify(auth=token)
# Create out geniusObject
geniusObject = lg.Genius(access_token)
...
while True:
currently_playing = spotifyObject.currently_playing()
artist = currently_playing['item']['artists'][0]['name']
title = currently_playing['item']['name']
search_query = artist + " " + title
# if (currently_playing has changed):
song = geniusObject.search_songs(search_query)
song_url = song['hits'][0]['result']['url']
webbrowser.open(song_url)
webbrowser.open(song_url)
I was reading relevant threads such as this, this, and read through documentation but could not find an answer to my question if this could be handled by Spotipy. I would appreciate any suggestions, thank you.
I used time.sleep(length) with the argument 'length' standing for the remaining duration of a current track.

Error when extracting info with youtube_dl

I'm currently making a program to transfer songs saved on my YT account into a Spotify playlist, and I am using youtube_dl to extract the meta data from the YT videos using the code below:
# use youtube_dl to collect the song name & artist name
video = youtube_dl.YoutubeDL({}).extract_info(
youtube_url, download=False)
song_name = video["track"]
artist = video["artist"]
When I was first made this project in March, the json that resulted from extract_info included the proper artist name, but now the artist, along with many other values (although not necessary for this task) are listed as None. Has anyone run into this issue? I'm considering a work around of not using the artist name to get the uri, but that would make it impossible to distinguish two songs with the same name. If anyone else has noticed this and has found a solution I'd love to hear it!
Setting the user-agent to Facebook's web crawler seems to solve this
youtube_dl.utils.std_headers['User-Agent'] = "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)"
Here is the video I tried your code with: https://www.youtube.com/watch?v=QBxSQXbj6Go
And the code and output from your snippet below.
Script:
[http_offline#greenhat-32 LEARNING]$ cat tests2.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import youtube_dl
# use youtube_dl to collect the song name & artist name
youtube_url = 'QBxSQXbj6Go'
video = youtube_dl.YoutubeDL({}).extract_info(youtube_url, download=False)
song_name = video["track"]
artist = video["artist"]
print(artist, ' - ', song_name)
[http_offline#greenhat-32 LEARNING]$
Output:
[http_offline#greenhat-32 LEARNING]$ ./tests2.py
[youtube] QBxSQXbj6Go: Downloading webpage
[youtube] QBxSQXbj6Go: Downloading MPD manifest
REO Speedwagon - Keep Pushin'
[http_offline#greenhat-32 LEARNING]$
youtube-dl can't extract Artist, Release Date and other certain fields from any video, it has to be a video with the description format like the video I provided above.
PS. it won't help you, but they released a new youtube-dl version a few days ago, you might want to grab it.

Is there a way to get YT url or video ID from playlist with pafy?

I am trying to make a program that takes YT playlist and play all it's content.
I've installed all components needed for pafy to run with python3. Everything I've tried works as it's expected, except the bellow part of the code.
plurl = "https://www.youtube.com/playlist?list=PL634F2B56B8C346A2"
playlist = pafy.get_playlist(plurl)
url = playlist['items'][21]['pafy'].getbest().url
video = pafy.new(url)
When pafy.new() is called, gives an error because of too long url:
Need 11 character video id or the URL of the video. Got https://r2---sn-bavc5aoxu-nv4l.googlevideo.com/videoplayback?ms=au%2Crdu&sparams=clen%2Cdur%2Cei%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cpl%2Cratebypass%2Crequiressl%2Csource%2Cexpire&mv=m&mt=1554899146&requiressl=yes&ip=37.157.173.53&pl=19&id=o-AGQZkyoEvykUGae7O4v_Ycmuj4jJBYdgafcfLBQ5S4Dd&mn=sn-bavc5aoxu-nv4l%2Csn-nv47lnsr&mm=31%2C29&source=youtube&lmt=1387649403290510&ei=POGtXJzdIo_ugAeEiL_wAQ&c=WEB&key=yt6&mime=video%2Fmp4&gir=yes&itag=18&clen=5461830&fvip=2&expire=1554920860&ratebypass=yes&dur=206.100&initcwndbps=1573750&ipbits=0&signature=AAA8B36CD3B402F587F874956595ACB928806C4F.D36C0A79E7F1727DB872425E696DBFC550AA7DF6
Is there a way I can get normal url or video ID ?
The videoid is also available in the url object. You can use
dir(<object>)
to see what properties are available.
id = playlist['items'][2]['pafy'].videoid
video = pafy.new('https://www.youtube.com/watch?v='+id)
use try and catch before using pafy.new , as some of the videos might not be available in the region.

Categories

Resources