基于fast-whisper模型的语音识别工具的设计与实现

目录

[摘 要](#摘 要)

[第1章 绪 论](#第1章 绪 论)

[1.1 论文研究主要内容](#1.1 论文研究主要内容)

1.1.1模型类型选择

1.1.2开发语言的选择

[1.2 国内外现状](#1.2 国内外现状)

[第2章 关键技术介绍](#第2章 关键技术介绍)

[2.1 关键性开发技术的介绍](#2.1 关键性开发技术的介绍)

[2.1.1 Faster-Whisper数据模型](#2.1.1 Faster-Whisper数据模型)

[2.1.2 Django](#2.1.2 Django)

[第3章 系统分析](#第3章 系统分析)

[3.1 构架概述](#3.1 构架概述)

[3.1.1 功能构架](#3.1.1 功能构架)

[3.1.2 模块需求描述](#3.1.2 模块需求描述)

[3.2 系统开发环境](#3.2 系统开发环境)

[3.3 系统任务的可行性分析](#3.3 系统任务的可行性分析)

[3.3.1 技术可行性](#3.3.1 技术可行性)

[3.3.2 系统安全性分析](#3.3.2 系统安全性分析)

[第4章 系统设计](#第4章 系统设计)

[4.1 设计指导思想和原则](#4.1 设计指导思想和原则)

[4.1.1 指导思想](#4.1.1 指导思想)

[4.1.2 软件设计原则](#4.1.2 软件设计原则)

[4.2 构架概述](#4.2 构架概述)

[4.3 系统的功能结构设计](#4.3 系统的功能结构设计)

[4.4 系统控制流程](#4.4 系统控制流程)

[5章 系统实现](#5章 系统实现)

[5.1 接口实现](#5.1 接口实现)

[5.1.1 验证账号接口](#5.1.1 验证账号接口)

[5.1.2 文件上传接口](#5.1.2 文件上传接口)

[5.1.3 语音识别接口](#5.1.3 语音识别接口)

[6章 系统测试](#6章 系统测试)

[6.1 测试方案及测试用例](#6.1 测试方案及测试用例)

[6.1.1 登录模块](#6.1.1 登录模块)

[6.1.1 用户管理模块](#6.1.1 用户管理模块)

[6.1.1 文件语音识别](#6.1.1 文件语音识别)

图6.3上传文件语音识别

[6.1.1 录屏语音识别](#6.1.1 录屏语音识别)

[第7章 结 论](#第7章 结 论)

参考文献


摘 要

随着人工智能的不断发展,AI智能语音识别在我们的生活中的应用越来越普遍,不管是在商场停车场出入车牌的识别、电影院语音播报、聊天工具中语音文本的识别等到处都可以见到AI智能语音识别在实际生活中的身影。其中Faster-Whisper实时语音识别技术在实时语音识别方面表现尤为突出,Faster-Whisper数据模型接入简单,可以跨多种平台,具有较高的实时性和准确性,它可以导入视频语音文件或录音进行实时识别,该模型还支持多语言识别,可以为用户提供更加高效便捷的音频识别使用体验,。

本文分以下几部分阐述了基于使用Faster-Whisper数据模型搭建语音实时识别系统的过程和api接口、数据库表的编写和实现过程。

关键词:智能AI;Faster-Whisper数据模型;mysql8

第1章 绪 论

这些年随着智能AI技术的不断发展,AI技术以便捷性、经济性得到社会各行各业的青睐。让传统只能依赖人工的行业有了更多的选择方案,而且智能AI技术和人工相比具有更好的稳定性、经济性,不容易受自身和周围环境的影响。一次接入就可永久使用,即使未来数据模型进行了升级和改变,也只需要升级相应的大数据模型,不必整个系统重新开发。

1.1 论文研究主要内容

当代人的交流方式不在像以前的人那样,人之间只能通过书信或传话的方式来进行信息的交互。随着智能手机的出现给人类开发更高效的交互软件带来了契机。有了硬件的支持,各类聊天软件应运而生,这些聊天软件往往集文字、视频、语音聊天于一身,虽然给人们带来了很大的方便,当毕竟视频和语音不像文字那样简单可以直接运用算法进行过滤非法信息,要是可以直接识别视频或语音的文字内容就可以直接识别出其是否包含非法信息,这时AI智能语音识别技术就有了大用处。该技术可以实时识别出视频、音频的文本内容,为非法信息的监管带来很大的帮助。

1.1.1模型类型选择

随着市面上各种各样的语音识别系统或工具的出现,识别文字内容的准确性和安全性是本次论文的主要研究内容,经研究Faster-Whisper数据模型有5中类型大数据模型,从tiny、base、 small、 medium到 large这5种模型,分层次的从模型规模、数量、精度上都有了提升,完全适用社会的各层的用户和企业使用,每一种类型的模型的识别准确性都有一定的提高,用户可以根据自己的需求自主选择相应的类型模型进行使用,极大的满足了用户的自主选择权。

1.1.2开发语言的选择

现在人们对于智能产品的性能要求越来越高,越来越偏向于智能类机器人方向。最好能生产一个复制的自己来完全替代自己,人类学习本身就是一种深度学习的过程,python语言的具有丰富的库,例如 NumPy、Pandas、Scikit-learn、TensorFlow,这些库可以使程序更好的进行数据分析、深度学习和自动化脚本的开发。Faster-Whisper数据模型底层也是用python语言进行编写的,所以此次系统选择python作为开发语言。

1.2 国内外现状

在当前的智能语音技术中,整个的行业技术趋于成熟。在标准语音、环境清晰的环境下语音的文字识别准确性可以达到95%以上,例如谷歌的语音助手,科大讯飞的语音识别技术等都在世界上处于领先水平。现在大部分公司的语音识别技术都支持多种语音的实时识别,在保证高准确性的情况下平均识别时间可以达到0.2秒左右,给用户带来极致的体验效果。这些年有些大型企业在语音识别技术上结合了深度学习技术,在嘈杂环境下的语音识别准确性也有了质的提高。总体来说,这些年国家发布多项对智能语音技术的支持法规,国内智能语音技术现在正在大型企业的牵头下,朝着和医疗、教育、智能驾驶、电子消费等领域相结合、多领域共同发展方面发展,可以说发展前景一片光明。

第2章 关键技术介绍

2.1 关键性开发技术的介绍

2.1.1 Faster-Whisper数据模型

Faster-Whisper 是一个基于 Whisper 模型的优化版本,旨在提高语音识别的速度和效率。Whisper 是由 OpenAI 开发的一个多语言、多任务的语音识别模型。它在多个基准测试中表现出色。它移除了模型中不必要的权重,最大限度的减少了模型的计算量。它还支持多线程和多CPU来加速推理的过程,减少运行成本。它还对解码器的算法进行了改良,提高了解码效率。

Faster-Whisper有tiny、base、 small、 medium、 large 5种模型类型,模型体积越大,推理时间相应越长,准确性也越高,用户可以根据自己要识别的语音文件的质量和硬件成本来选择适合自己的模型类型。

2.1.2 Django

django是用python编写的高级web框架,它遵循了MVC架构,提供了一个更加强大的ORM可以更好的操作数据库。它还自带操作管理界面,可以自动生成对数据库增删改查的代码。它使用url路由方式来定义url和视图函数直接的关系,而却它还内置了许多具有安全特性的插件,可以自动过滤sql注入、xss攻击等。它还支持中间件,可以让开发者自主编写,过滤非法请求。它的架构设计使得应用可以轻松的进行扩展,支持大型项目的高并发场景。它还支持多语言和多地区设置。

第3章 系统分析

3.1 构架概述

3.1.1 功能构架

根据需求调研结果确定本系统主要包括以下功能模块,如图3.1所示。

图3.1 系统体系结构

3.1.2 模块需求描述

(1)登录模块

系统采用用户名、密码和验证码登录,只有当3个都正确的时候才能验证通过访问系统的主界面,要是登录信息不正确,系统会给出相应的错误提示。

(2)用户管理模块

该模块会以表格的形式展示系统中全部的用户账号信息,可以对每个用户信息进行增删改查操作,也可以禁用某一个用户账号信息限制其访问系统。

  1. 文件语音识别模块

该模块允许用户上传wav、mp3、flac、mp4、mov、mkv、avi、mpeg等视频或语音文件然后点击立即识别按钮,上传文件就会被提交到后台接口,后台接口调用Faster-Whisper数据模型进行语音识别,然后再返回识别结果(识别的文字结果会进行,。、?''"";:({}【】):;"\'\s \d`!@#%\^\&\*()_+=.,?/\\\\-\]\*等非法字符的过滤),前端进行结果展示。

(4)录音语音识别模块

该模块支持调用系统自带的录音模块进行实时录音,然后点击立即识别按钮,即可实时上传录音文件进行语音识别,然后再返回结果(识别的文字结果会进行,。、?''"";:({}【】):;"\'\s \d`!@#%\^\&\*()_+=.,?/\\\\-\]\*等非法字符的过滤),前端进行结果展示。

3.2 系统开发环境

硬件环境:安装win10系统的PC

软件环境:pycharm、mysql8

3.3 系统任务的可行性分析

3.3.1 技术可行性

(1)本系统采用pycharm作为开发软件,该软件具有自动代码排版、补齐、断点调试等功能。还支持GIT、SVN等工具,可以使开发者更好的进行错误排查和项目版本的管控。采用python作为开发语言,该语言语法简洁明了,接近自然语言,学习容易上手,语言本身集成的第三方库可以无条件的支持数据分析和深度学习操作。数据库采用mysql8。整个系统采用djanog框架搭建,该框架具有强大的ORM关系映射属性,支持多种数据库,可以自动生成数据库表,提供丰富的查询接口,简化查询语句的编写。采用html、css、js等技术相结合来编写系统所需的界面。pycharm和mysql8等软件都是免费开源的,可以直接下载使用,极大的降低了搭建人的经济压力。django框架和mysql8数据、html界面的各层之间具有良好的解耦性,极大的降低了后期系统的维护成本。

3.3.2 系统安全性分析

(1)本系统采用django作为系统框架,由python语言开发完成。python拥有大量的第三方库,如机器学习、数据分析等为实时语音的文本识别提供了技术支持。python还具有良好的跨平台性和兼容性,为后期系统的跨平台使用提供了支持。djaong框架内置了多种安全处理机制,可以有效的防止web安全漏洞、sql注入、跨站xss脚本攻击等,django系统的中间件技术可以由开发者自主编写程序过滤非法请求,为系统的安全性提供保证。

第4章 系统设计

4.1 设计指导思想和原则

4.1.1 指导思想

(1)对比了java、python、C#等开发语言的优缺点和自己的熟练度,最后决定使用python来作为此次系统的开发语言,pycharm作为此次系统的开发软件,mysql8数据库作为此次系统各类数据的存储。

(2)为了保证系统的安全性和稳定性,该系统采用django来作为后端框架,根据实际情况编写了中间件类对非法请求进行了过滤,为了最大限度的降低系统和数据库的解耦性,采用models来对数据库进行增删改查操作。

(3)为了保证系统界面具有良好的结构化,采用传统的html、css、js来编写系统界面,为了使界面更加美观和开发的简洁性,引入了layui来进行界面日期、输入框、图片上传等组件的构造。

4.1.2 软件设计原则

(1)django系统的开发应该保证单一职责性,每个视图或类通常只处理一类的处理请求,每个模型通常也只表示一种数据库操作或数据实体。

(2)django系统的开发应该保持简单开发的原则,在编写代码的时候要尽量保证项目的文件分层化,代码结构化,逻辑简单化,注意代码的复用,避免编写重复逻辑代码。尽量保持配置文件的简洁,避免冗余配置。

(3)django系统的开发要保证系统的安全性,时刻防止依赖注入,将依赖关系从代码中分离开来,通过构造函数或属性输入服务类,提高代码的可维护性。将连接数据库配置保存在配置文件中,把其他配置信息保存在数据库表中,提高系统的安全性。

4.2 构架概述

(1)本系统采用分层架构即MVC架构,该架构一般适用于传统的单体项目中,该架构把系统分成3层,每一层都有相应的特定功能。

(2)表示层:主要作用为处理用户和界面的交互,接受用户的输入并把请求输入传递给业务逻辑层,返回业务逻辑层的处理结果给界面进行数据展示。

(3)业务逻辑层:主要作用为根据请求输入完成具体的业务逻辑处理,调用数据访问层进行数据的存储和检索。

(4)数据访问层:主要作用为和数据库的交互,存储和管理数据库,保证数据的完整性和一致性。

4.3 系统的功能结构设计

(1)为了fast-whisper模型的语音识别工具具有更好的使用体验和结合自己4年所学知识的熟练性,还有考虑系统的安全行和稳定性,决定采用python作为系统的开发语言,django作为后端接口框架,

(2)考虑到数据库的稳定性和兼容性所以选择mysql8作为本次系统的数据库。fast-whisper模型有5种数据模型,由于其官网在国外,国内下载速率很慢,所以只下载了small和larger-v1两种数据模型,考虑到自己电脑的CPU情况和接口返回数据时效性,本论文中的全部测试截图全部采用small数据模型测试而来。

3)为了降低业务逻辑层和数据库的解耦性,系统采用django框架的models来和数据库进行数据交互,后期系统即使更换数据库,也无需修改业务逻辑层代码。

4.4 系统控制流程

(1)系统由前端html界面、django框架业务逻辑处理接口、mysql8数据库组成,用户登录成功后,由首页具体的功能界面操作发起具体的操作请求,请求调用后端业务逻辑处理接口,进行相应的逻辑处理之后,访问数据库进行相应的数据操作,把数据同步到数据库中,最终再把结果逐层返回给前端界面进行数据展示。

5章 系统实现

5.1 接口实现

5.1.1 验证账号接口

账号验证接口会先验证验证码是否正确,然后在验证用户名和密码在用户表中是否存在该账号信息,要是不存在就返回"用户名或密码不正确"给登录界面,要是账号验证通过就返回200标准码给登录界面。

python 复制代码
def loginCon(request):

    if request.method == 'POST':

        username = request.POST.get("username", None)

        password = request.POST.get("password", None)

        verify = request.POST.get("verify", None)

        if verify == None:

            return JsonResponse({"code": 400, "message": "验证码不能为空"}, safe=False)

        if username == None or password == None:

            return JsonResponse({"code": 400, "message": "用户名或密码不能为空"}, safe=False)

        yzm = request.session['yzm'];

        print('yzm', yzm)

        if yzm != verify:

            return JsonResponse({"code": 400, "message": "验证码不正确"}, safe=False)

        userList = models.User.objects.filter(username=username, password=password, status=1).values()

        if userList.count() > 0:

            print(userList[0])

            print(userList[0]['id'])

            request.session['loginId'] = userList[0]['id'];

            request.session['loginType'] = 'user';

            request.session['loginAccount'] = username

            return JsonResponse({"code": 200, "message": "账号验证成功", 'data': list(userList)},

                                safe=False)

        else:

            return JsonResponse({"code": 400, "message": "用户名或密码不正确"}, safe=False)

5.1.2 文件上传接口

上传的文件会进行文件的原名保存在项目的static/upload文件夹下,要是上传同名文件会进行直接覆盖操作,文件保存成功后把文件名返回给前端界面。

复制代码
python 复制代码
def upload(request):

    try:

        # 获取上传的文件

        audio_file = request.FILES.get('audio')

        # 如果是mp4

        noextname, ext = os.path.splitext(audio_file.name)

        ext = ext.lower()

        # 如果是视频,先分离

        wav_file = os.path.join(cfg.TMP_DIR, f'{noextname}{ext}')



        video_file = os.path.join(cfg.TMP_DIR, f'{noextname}{ext}')

        file = audio_file.read()

        with open(video_file, 'wb') as f:

            f.write(file)



        if os.path.exists(wav_file) and os.path.getsize(wav_file) > 0:

            return JsonResponse({'code': 0, 'msg': cfg.transobj['lang1'], "data": os.path.basename(wav_file)})

        msg = ""

        if ext in ['.mp4', '.mov', '.avi', '.mkv', '.mpeg', '.mp3', '.flac', '.wav']:



            params = [

                "-i",

                video_file,

            ]

            if ext not in ['.mp3', '.flac']:

                params.append('-vn')

            params.append(wav_file)

            rs = tool.runffmpeg(params)

            if rs != 'ok':

                return JsonResponse({"code": 1, "msg": rs})

            msg = "," + cfg.transobj['lang9']

        else:

            return JsonResponse({"code": 1, "msg": f"{cfg.transobj['lang3']} {ext}"})



        # 返回成功的响应

        return JsonResponse({'code': 0, 'msg': cfg.transobj['lang1'] + msg, "data": os.path.basename(wav_file)})

    except Exception as e:

        print(f'[upload]error: {e}')

        return JsonResponse({'code': 2, 'msg': cfg.transobj['lang2']})
}

5.1.3 语音识别接口

先判断提交的要识别文件在static/upload文件夹下是否存在,要是存在就创建一个子线程调用语音识别模型进行语音识别操作,然后前端界面在定时请求接口取子线程的返回结果在前端界面进行结果展示。

python 复制代码
def process(request):

    # 原始字符串

    wav_name = request.POST.get("wav_name").strip()

    model = request.POST.get("model")

    # 语言

    language = "zh"

    # 返回格式 json txt srt

    data_type = "srt"

    wav_file = os.path.join(cfg.TMP_DIR, wav_name)

    if not os.path.exists(wav_file):

        return JsonResponse({"code": 1, "msg": f"{wav_file} {cfg.langlist['lang5']}"})

    if not os.path.exists(os.path.join(cfg.MODEL_DIR, f'models--Systran--faster-whisper-{model}/snapshots/')):

        return JsonResponse({"code": 1, "msg": f"{model} {cfg.transobj['lang4']}"})

    key = f'{wav_name}{model}{language}{data_type}'

    # 重设结果为none

    cfg.progressresult[key] = None

    # 重设进度为0

    cfg.progressbar[key] = 0

    # 新线程启动实际任务

    threading.Thread(target=shibie,

                     kwargs={"wav_name": wav_name, "model": model, "language": language, "data_type": data_type,

                             "wav_file": wav_file, "key": key}).start()

    return JsonResponse({"code": 0, "msg": "ing"})

def shibie(*, wav_name=None, model, language=None, data_type=None, wav_file=None, key=None):

    try:

        sets = cfg.parse_ini()

        print(f'{sets.get("initial_prompt_zh")}')

        print(cfg.ROOT_DIR)

        modelobj = WhisperModel(model, device=sets.get('devtype'), compute_type=sets.get('cuda_com_type'),

                                download_root=cfg.ROOT_DIR + "/models", local_files_only=True)

        cfg.progressbar[key] = 0

        segments, info = modelobj.transcribe(wav_file, beam_size=sets.get('beam_size'), best_of=sets.get('best_of'),

                                             temperature=0 if sets.get('temperature') == 0 else [0.0, 0.2, 0.4, 0.6,

                                                                                                 0.8, 1.0],

                                             condition_on_previous_text=sets.get('condition_on_previous_text'),

                                             vad_filter=sets.get('vad'),

                                             vad_parameters=dict(min_silence_duration_ms=300), language=language,

                                             initial_prompt=None if language != 'zh' else sets.get('initial_prompt_zh'))

        total_duration = round(info.duration, 2)  # Same precision as the Whisper timestamps.



        raw_subtitles = []

        for segment in segments:

            cfg.progressbar[key] = round(segment.end / total_duration, 2)

            start = int(segment.start * 1000)

            end = int(segment.end * 1000)

            startTime = tool.ms_to_time_string(ms=start)

            endTime = tool.ms_to_time_string(ms=end)

            text = segment.text.strip().replace(''', "'")

            text = re.sub(r'&#\d+;', '', text)



            # 无有效字符

            if not text or re.match(r'^[,。、?''"";:({}【】):;"\'\s \d`!@#$%^&*()_+=.,?/\\-]*$', text) or len(

                    text) <= 1:

                continue

            if data_type == 'json':

                # 原语言字幕

                raw_subtitles.append(

                    {"line": len(raw_subtitles) + 1, "start_time": startTime, "end_time": endTime, "text": text})

            elif data_type == 'text':

                raw_subtitles.append(text)

            else:

                raw_subtitles.append(f'{len(raw_subtitles) + 1}\n{startTime} --> {endTime}\n{text}\n')

        cfg.progressbar[key] = 1

        if data_type != 'json':

            raw_subtitles = "\n".join(raw_subtitles)

        cfg.progressresult[key] = raw_subtitles

    except Exception as e:

        cfg.progressresult[key] = str(e)

        print(str(e))

5.1.4 录音接口

当前端点击开始录音按钮就先定义一个全局变量记录创建的录音实例,当前端点击结束录音的按钮时,就获取之前定义的全局对象进行停止录音操作,然后保存生成的录音文件到static/upload文件夹下,把保存文件名称返回给前端界面。

python 复制代码
p = None;

stream = None;

frames = []

WAVE_OUTPUT_FILENAME = pathname

CHUNK = 1024

FORMAT = pyaudio.paInt16

CHANNELS = 2

RATE = 16000

RECORD_SECONDS = 2

isLY = 1





def startLy(request):

    global p

    global stream

    global frames

    global isLY



    p = None;

    stream = None;

    frames = []

    isLY = 1



    p = pyaudio.PyAudio()



    stream = p.open(format=FORMAT,

                    channels=CHANNELS,

                    rate=RATE,

                    input=True,

                    frames_per_buffer=CHUNK)



    print("开始录音,请说话......")



    frames = []



    while isLY:

        data = stream.read(CHUNK)

        frames.append(data)



    return JsonResponse({"code": 0, "data": "", "msg": "ok"})





def endLy(request):

    global p

    global stream

    global frames

    global isLY



    print("录音结束......")



    isLY = 0



    stream.stop_stream()

    stream.close()

    p.terminate()



    uid = str(uuid.uuid4())

    suid = ''.join(uid.split('-')) + ".wav"



    wf = wave.open(WAVE_OUTPUT_FILENAME + suid, 'wb')

    wf.setnchannels(CHANNELS)

    wf.setsampwidth(p.get_sample_size(FORMAT))

    wf.setframerate(RATE)

    wf.writeframes(b''.join(frames))

    wf.close()



    return JsonResponse({"code": 0, "data": suid, "msg": "ok"})

6章 系统测试

由于考虑自身电脑的CPU 性能问题、语言文本识别的速率问题、识别结果的准确性、识别文件质量等因数,所以系统采用samll的数据模型来进行测试。

6.1 测试方案及测试用例

6.1.1 登录模块

用户输入用户名、密码、验证码点击登录按钮进行登录验证,登录成功后即可跳转到主界面,

要是输入为空、不正确的情况下都会有相应的错误提示语进行提示。

图6.1用户登录验证

6.1.1 用户管理模块

用户登录成功后可以单击左边的用户管理模块,可以各个用户的信息进行新增、编辑、删除和查询(支持关键字模糊查询)等操作。

图6.2用户管理

6.1.1 文件语音识别

该模块支持用户上传wav、mp3、flac、mp4、mov、mkv、avi、mpeg等类型格式的音频文件进行语音文字识别,还支持识别结果进行文本导出操作。

图6.3上传文件语音识别

6.1.1 录屏语音识别

该模块支持使用电脑进行录音操作然后点击立即识别按钮即可进行语音文本识别,还支持识别结果进行文本导出操作。

图6.4录音语音识别

第7章 结 论

当前,我们国家经过几十年的发展,人们的生活水平和娱乐方式都发生了巨大变化,传统的书信、短信等通信方式已经无法满足人们的日常生活交互需求。各种网上聊天app如雨后春笋般出现,这些app不仅能发文字信息,还可以直接发送语音文件和进行网上视频,这些聊天方式虽然极大的方便了人们的交互方式,但也给相应企业和政府监管部门带来新的挑战和压力。

有些非法分子,就利用语音不容易监管的缺陷,就恶意建群传播非法音频文件,获取非法收入。这时随着智能AI技术的成熟,以Faster-Whisper为基础的语音文本识别技术的出现,给语音的识别带来了极大的便利,该技术可以统一的对语音文件进行文本识别,然后就可以运行算法对识别的文字进行过滤操作了,判断其是否包括非法信息了,可以给企业和政府的监管人员带来极大的便利。Faster-Whisper有tiny、base、 small、 medium、 large 5种模型,不同的模型提供了不同的识别精度,对语音文件的质量要求也不一样,企业和监管人员可以根据语音文件的质量进行分类,采用相应的模型进行文本识别,可以极大的降低识别时间,提高工作效率。此次系统除了可以上传wav、mp3、flac、mp4、mov、mkv、avi、mpeg等类型文件进行语音的识别还支持直接录音进行语音识别,使使用者不用考虑要进行语音识别文件的格式问题,极大的丰富了语音识别的使用场景。

参考文献

[1] 明日科技.Python从入门到精通(第3版)[J].北京:清华大学出版社,2023:19.

[2] 芯智.Python数据可视化:科技图表绘制[D].北京:清华大学出版社,2024:16.

[3] Silvia Botros,Jeremy Tinley.高性能MySQL(第4版)[D].西安:电子工业出版社,2022:11.

[4] 张文亮.MySQL应用实战与性能调优[B].北京:机械工业出版社,2022.

[5] 黄索远.Django项目开发实战[M].北京:清华出版社,2020:18.

[6] 张晓.Django实战 Python Web模块与项目开发 Web框架应用开发实战前端开发后端开发Py[D].北京:人民邮电出版社,2020.5

[7] 段艺,涂伟忠.Django开发从入门到实践[J].北京:机械工业出版社,2016.9

[8] Jesper Wisborg Krogh.MySQL 8查询性能优化[D].北京:清华大学出版社,2021:8.

[9] 未来科技.HTML5+CSS3+JavaScript从入门到精通(标准版)[J].北京:水利水电出版社,2014:16.

[10] AdamFreeman.Web开发经典丛书ANGULAR 高级编程第3版[G].北京:清华大学出版社,2019:6.

[11] 阿尔.Python编程快速上手 让繁琐工作自动化 第2版[M].北京:人民邮电出版社,2021:3.

[12] Caleb Hattingh.Python异步编程[J].北京:中国电力出版社,2023:5.

[13] 邓立国李剑锋林庆发邓淇文.Python深度学习原理、算法与案例[G].北京:清华大学出版社,2021:4.

[14] 吴茂贵 郁明敏 杨本法 李涛 .Python深度学习:基于PyTorch 第2版[J].北京:机械工业出版社,2023:1.

[15] 张良均 谭立云 刘名军 江建明.Python数据分析与挖掘实战(第2版)[M].北京:机械工业出版社,2019:9.

相关推荐
我不会编程5552 小时前
Python Cookbook-2.24 在 Mac OSX平台上统计PDF文档的页数
开发语言·python·pdf
胡歌13 小时前
final 关键字在不同上下文中的用法及其名称
开发语言·jvm·python
程序员张小厨3 小时前
【0005】Python变量详解
开发语言·python
计算机-秋大田4 小时前
基于Spring Boot的乡村养老服务管理系统设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·课程设计
Arbori_262154 小时前
hive 面试题
大数据·数据仓库·hive·hadoop
Hacker_Oldv4 小时前
Python 爬虫与网络安全有什么关系
爬虫·python·web安全
深蓝海拓4 小时前
PySide(PyQT)重新定义contextMenuEvent()实现鼠标右键弹出菜单
开发语言·python·pyqt
车载诊断技术5 小时前
人工智能AI在汽车设计领域的应用探索
数据库·人工智能·网络协议·架构·汽车·是诊断功能配置的核心
B站计算机毕业设计超人6 小时前
计算机毕业设计SpringBoot+Vue.js校园失物招领系统(源码+文档+PPT+讲解)
java·vue.js·spring boot·后端·毕业设计·课程设计·毕设
计算机-秋大田6 小时前
基于SpringBoot的环保网站的设计与实现(源码+SQL脚本+LW+部署讲解等)
java·vue.js·spring boot·后端·课程设计