问题描述
信息:
我正在使用模块PyTube(3)构建一个Youtube Downloader Web App。 它基于Flask
其他文件的工作
:使用YouTubedownload.py
文件,因此在app.py
文件中,所有内容都很干净。
它用于清除不需要的数据
工作原理:
首先在索引中呈现HTML页面,其中包含带有URL输入表单的表单,该表单将其提交到“ / details”。 运行onsubmit函数以显示加载的gif。
<form action="/details" method="POST" onsubmit="navigateLoading()" id="yt-url" >
<input placeholder="Paste video link" class="light-skinish-bg" type="url" name="url" id="url" />
</form>
然后将网址传递到yt对象,该对象是从YouTubedownload.py的YoutubeVideo初始化的
然后使用try,除了不同的例外,它使用JINJA和stream_id传递可下载到HTML页面的流列表。
然后将流ID设置为“下载/-流的ID”。例如“下载/ 5” 因此,称为“ / download /”,它从url中获取流ID,然后根据该ID下载流,并在下载完成后运行一个名为redirectUser的函数。
重定向用户功能将bool作为str和下载的视频/音频文件名传递到HTML页面(脚本标记内部),然后将用户重定向到“ / download / f /--file -name- from js” >
然后donwload / f / filename使用flask的_directory从目录返回文件。
注意:我已经使许多变量成为全局变量,因此可以从不同的函数访问它们!
错误:
我收到的JSON类型错误完全不在上下文中,因为我没有使用它,所以似乎所有模块中都存在一些问题。
我也在下面提到错误!
app.py
from flask import Flask,request,render_template,send_from_directory,Response,redirect,flash
from Youtubedownload import YoutubeVideo
from threading import Timer
from datetime import datetime
import os
import sys
# Flask App Initialize
app = Flask("__name__")
#App Configurations
app.secret_key = '-secret-key-'
# Global variables
yt = ""
url = ""
streams = ""
download_file_name = ""
# req vars
isAudio = False
delay_in_secs = 5
downloadStatus = False
YOUTUBE_FILES = "YouTube_Files"
# Remove the downloaded file from the directory
def removeFile(fileName):
os.remove(os.path.join(YOUTUBE_FILES,fileName))
# Download Status to True for redirection and run remove file function
def redirectUser(stream,filepath):
global downloadStatus,download_file_name,isAudio
downloadStatus = True
download_file_name = os.path.basename(filepath)
if isAudio:
download_file_name = os.path.splitext(download_file_name)[0] + ".mp3"
audio_file_path = os.path.join(YOUTUBE_FILES,download_file_name)
os.rename(filepath,audio_file_path)
thread = Timer(delay_in_secs,removeFile,[download_file_name])
thread.start()
# Get file extension from filename
def get_file_extension(filename):
if not "." in filename:
return False
return filename.rsplit(".",1)[1].upper()
# Check whether the request was for an audio or video
def checkFileRequest(streams,stream_id):
for i in range(len(streams)):
if str(streams[i][0]) == str(stream_id):
if "audio" in str(streams[i][3]):
return True
else:
return False
# Index url for site
@app.route("/",methods=["GET"])
@app.route("/index")
def index():
return render_template("index.html")
# Details on form POST request and displays streams
@app.route("/details",methods=["POST"])
def details():
if request.method == "POST":
try:
yturl = request.form.get("url")
except AttributeError as a:
return redirect("/",404)
global yt,streams
try:
yt = YoutubeVideo(yturl)
except:
error = sys.exc_info()
if "get_ytplayer_config" in str(sys.exc_info()[1]):
flash("Enter valid video url!")
return redirect("/")
elif "getaddrinfo Failed" in str(sys.exc_info()[1]):
network = False
flash("Failed to get data. Please check your internet connection","danger")
return redirect("/")
else:
flash(error,"danger")
redirect("/")
try:
streams = yt.get_streams()
details = yt.get_details()
except AttributeError as e:
flash("Enter a valid youtube url!")
return redirect("/")
return render_template('details.html',streams=streams,details=details)
else:
return redirect("/")
#On visiting this with stream id it will redirect to send it from dir
@app.route("/download/<string:stream_id>",methods=["GET"])
def download(stream_id):
global yt,downloadStatus,streams,isAudio
isAudio = checkFileRequest(streams,stream_id)
try:
yt.download_complete(redirectUser)
yt.download(stream_id,YOUTUBE_FILES)
except AttributeError as e:
flash("Something went wrong,please try again!")
return redirect("/")
return render_template("download.html",downloadStatus=downloadStatus,fileName=download_file_name)
#Send the file from dir
@app.route("/download/f/<string:file_name>",methods=["GET"])
def returnFile(file_name):
return send_from_directory(YOUTUBE_FILES,file_name,as_attachment=True)
@app.errorhandler(404)
def pagenotFound(error):
return render_template("404.html")
@app.errorhandler(405)
def methodNotAllowed(error):
return render_template("405.html")
if __name__ == "__main__":
app.run(debug=True,port=5001)
这是错误日志:
Traceback (most recent call last):
File "F:\Youtube Do\venv\lib\site-packages\flask\app.py",line 2464,in __call__
return self.wsgi_app(environ,start_response)
File "F:\Youtube Do\venv\lib\site-packages\flask\app.py",line 2450,in wsgi_app
response = self.handle_exception(e)
File "F:\Youtube Do\venv\lib\site-packages\flask\app.py",line 1867,in handle_exception
reraise(exc_type,exc_value,tb)
File "F:\Youtube Do\venv\lib\site-packages\flask\_compat.py",line 39,in reraise
raise value
File "F:\Youtube Do\venv\lib\site-packages\flask\app.py",line 2447,in wsgi_app
response = self.full_dispatch_request()
File "F:\Youtube Do\venv\lib\site-packages\flask\app.py",line 1953,in full_dispatch_request
return self.finalize_request(rv)
File "F:\Youtube Do\venv\lib\site-packages\flask\app.py",line 1970,in finalize_request
response = self.process_response(response)
File "F:\Youtube Do\venv\lib\site-packages\flask\app.py",line 2269,in process_response
self.session_interface.save_session(self,ctx.session,response)
File "F:\Youtube Do\venv\lib\site-packages\flask\sessions.py",line 378,in save_session
val = self.get_signing_serializer(app).dumps(dict(session))
File "F:\Youtube Do\venv\lib\site-packages\itsdangerous\serializer.py",line 166,in dumps
payload = want_bytes(self.dump_payload(obj))
File "F:\Youtube Do\venv\lib\site-packages\itsdangerous\url_safe.py",line 42,in dump_payload
json = super(URLSafeSerializerMixin,self).dump_payload(obj)
File "F:\Youtube Do\venv\lib\site-packages\itsdangerous\serializer.py",line 133,in dump_payload
return want_bytes(self.serializer.dumps(obj,**self.serializer_kwargs))
File "F:\Youtube Do\venv\lib\site-packages\flask\json\tag.py",line 305,in dumps
return dumps(self.tag(value),separators=(",",":"))
File "F:\Youtube Do\venv\lib\site-packages\flask\json\__init__.py",line 211,in dumps
rv = _json.dumps(obj,**kwargs)
File "c:\users\sohel\appdata\local\programs\python\python37\lib\json\__init__.py",line 238,in dumps
**kw).encode(obj)
File "c:\users\sohel\appdata\local\programs\python\python37\lib\json\encoder.py",line 199,in encode
chunks = self.iterencode(o,_one_shot=True)
File "c:\users\sohel\appdata\local\programs\python\python37\lib\json\encoder.py",line 257,in iterencode
return _iterencode(o,0)
File "F:\Youtube Do\venv\lib\site-packages\flask\json\__init__.py",line 100,in default
return _json.JSONEncoder.default(self,o)
File "c:\users\sohel\appdata\local\programs\python\python37\lib\json\encoder.py",line 179,in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type type is not JSON serializable
Youtubedownload.py
from pytube import YouTube
import requests
class YoutubeVideo():
def __init__(self,url):
self.url = url
self.Video = YouTube(url)
self.streams = self.Video.streams
def convert_bytes(self,size):
"""
Returns size in KB/MD ...
Takes 1 argument:
size -int: Bytes
"""
for i in ['bytes','KB','MB','GB','TB']:
if size < 1024.0:
return "%3.1f %s" % (size,i)
size /= 1024.0
return size
def removeDuplicateStreams(self,streams):
videoStreamQuality = []
videoStreamPosition = []
videoNewStreams = []
audioStreamSize = []
audioStreamPosition = []
newAudioStream = []
for i in range(len(streams)):
if "video" in str(streams[i][3]):
if not "None" in str(streams[i][1]):
if not "webm" in str(streams[i][3]):
if not streams[i][1] in videoStreamQuality:
videoStreamQuality.append(streams[i][1])
videoStreamPosition.append(i)
elif "audio" in str(streams[i][3]):
if not streams[i][2] in audioStreamSize:
audioStreamSize.append(streams[i][2])
audioStreamPosition.append(i)
for i in range(len(videoStreamPosition)):
videoNewStreams.append(streams[videoStreamPosition[i]])
videoNewStreams.sort(key=lambda tup: tup[1])
for i in range(len(audioStreamPosition)):
audioStream = streams[audioStreamPosition[i]]
if str(audioStream[1]) == "None":
lst = list(audioStream)
lst[1] = "Audio"
audioStream = tuple(lst)
newAudioStream.append(audioStream)
return videoNewStreams + newAudioStream
def get_origianl_streams(self):
""""
Returns list of original streams directly from pytube
"""
return self.streams
def get_streams(self):
"""
Returns array of streams with
stream_id,stream_resolution,stream_filesize,stream_mime_type
"""
newStream = []
for i in range(len(self.streams)):
# if not "/webm" in str(self.streams[i].mime_type):
listStream = (i,self.streams[i].resolution,self.convert_bytes(self.streams[i].filesize_approx),self.streams[i].mime_type)
newStream.append(listStream)
return self.removeDuplicateStreams(newStream)
def download(self,stream_id,file_path = None):
"""
Dowloads the video:
Takes 2 arguments:
stream_id - int: id of stream (found in get_streams())
file_path - str: (Optional) Path where file is to be downloaded,default is working dir!
"""
stream_id = self.get_streams()[0][0]
self.Video.streams[stream_id].download(file_path)
def get_details(self):
"""
Returns details in tuple
(thumbnailUrl,title,authorName,url)
"""
title = self.Video.title
authorName = self.Video.author
thumbnailUrl = self.Video.thumbnail_url
return (thumbnailUrl,self.url)
def download_progress(self,func):
"""
Rreturns functional arguments:
chunk which also conatain filesize
filehandle,file_size
"""
self.Video.register_on_progress_callback(func)
def download_complete(self,func):
"""
Return functional argument:
filepath;
"""
self.Video.register_on_complete_callback(func)
if __name__ == "__main__":
url = "https://youtu.be/6kwrsqlQnhA"
url = "https://www.youtube.com/watch?v=GwgXoPBt0dM"
yt = YoutubeVideo(url)
print(yt.get_origianl_streams())
print(yt.get_details())
print(yt.get_streams())
# yt.download(2)
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)