Flask使用PyTube Youtube下载应用引发了JSON序列化错误

问题描述

信息:

我正在使用模块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 (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...