精华内容
下载资源
问答
  • Python打包exe文件方法汇总【4种】

    万次阅读 多人点赞 2018-10-21 22:15:11
    title: Python打包exe文件方法 copyright: true top: 0 date: 2018-08-11 21:08:21 tags: 打包 categories: Python进阶笔记 permalink: password: keywords: description: 使用py2exe,pyinstaller,cx_Freeze,...

    title: Python打包exe文件方法
    copyright: true
    top: 0
    date: 2018-08-11 21:08:21
    tags: 打包
    categories: Python进阶笔记
    permalink:
    password:
    keywords:
    description: 使用py2exe,pyinstaller,cx_Freeze,nuitka对python文件进行打包,尝试进行混淆代码。

    “乔治是世界上最后一只平塔岛象龟,而我是世界上最后一个源家后裔,最后一只平塔岛象龟应该为了种族不灭努力地繁殖后代,最后一个源家后裔应该重振家族在黑道中的威望,但是乔治只是想回自己的水坑里去打滚,而我只是想去天体海滩上卖防晒油。”源稚生盯着恺撒的眼睛,“我就是这种人,其实蛇岐八家的黑道事业和秘党的使命对我来说都不重要,我的人生理想就是去卖防晒油。我跟你叔叔不是一种人。”

    Python作为解释型语言,发布即公开源码,虽然是提倡开源但是有些时候就是忍不住想打包成exe,不仅仅是为了对代码进行加密,而是为了跨平台。防止有些没有安装py环境的电脑无法运行软件。

    目录对python代码打包成exe的方式有4种,py2exe,pyinstaller,cx_Freeze,nuitka,分别对以上4种方法介绍,欢迎纠错和提供新的办法。

    py2exe

    介绍

    py2exe是一个将python脚本转换成windows上的可独立执行的可执行程序(*.exe)的工具,这样,你就可以不用装python而在windows系统上运行这个可执行程序。

    优点:

    1. 可以把python打包成exe

    缺点:

    1. 打包好的 exe只能在相同的系统下运行,比如你在XP系统用py2exe打包好的exe只能在XP上运行,在win7上肯定有问题,而且也是存在在别的XP机子上也可能不能运行,因为一些别的机子可能会缺少dll文件什么的,作者我当时之所以抛弃py2exe 也是因为这个原因;

    2. 打包的文件也需要打包同exe下的dll,和一些库的压缩包,不然exe根本跑不起来

    3. 打包时候报始终报RuntimeError: BeginUpdateResource错误,就需要拷贝dll文件。C:\WINDOWS\system32\python27.dll复制到dist目录

    4. 总之毛病一大堆,基本上已经舍弃了

    使用

    下载地址

    安装好后,准备进行打包

    准备一个文件x.py,这个x.py就是想要打包成exe。

    然后这x.py同目录下新建一个setup.py,内容如下:

    #coding=utf-8
    from distutils.core import setup
    import py2exe
    includes = ["encodings", "encodings.*"]
    #要包含的其它库文件
    options = {"py2exe":
      {
        "compressed": 1, #压缩
        "optimize": 2,
        "ascii": 1,
        "includes": includes,
        "bundle_files": 1 #所有文件打包成一个exe文件
      }
    }
    setup (
      options = options,
      zipfile=None,  #不生成library.zip文件
      console=[{"script": "x.py", "icon_resources": [(1, "Q.ico")] }]#源文件,程序图标
    )
    

    然后这cmd窗口下运行:

    python setup.py py2exe
    

    py2exe使用方法 (含一些调试技巧,如压缩email 类)

    pyinstaller

    PyInstaller除了win32平台外还支持Linux,Unix平台.py2exe的用法在前面的博文里已经有了,现在看看PyInstaller,pyinstaller是目前应用最多的python打包工具,也是我最常用的。

    PyInstaller本身并不是Python模块,所以安装时随便放在哪儿都行。

    优点:

    1. 可将python文件转成可执行文件
    2. 跨平台
    3. 输出的可以是单一目录,也可以是一个单独的打好包的可执行文件。py2exe貌似输出目录。
    4. 智能支持python的第三方模块如PyQt,外部数据文件等
    5. 支持EGG格式文件
    6. 可执行文件可以用UPX压缩,二进制压缩方式
    7. 支持控制台和视窗两种方式。
    8. 可以选择exe文件的图标 (Windows only)
    9. 支持 COM server (Windows only)

    缺点:

    1. import导入的问题

    pyinstaller是很智能的,只要指定了入口py文件,那么它就会根据代码自动查找需要导入的包。但是隐式导入的话,平常运行是没有问题的,举例:

    # test1.py
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker
     
     
    DB_CONNECT_STRING = 'mysql+pymysql://root:123456@localhost/study'
    engine = create_engine(DB_CONNECT_STRING, echo = False)
    DB_Session = sessionmaker(bind = engine)
    session = DB_Session()
     
    print('this is my test')
    

    运行这个ORM库的初始化引擎,是没有问题的,在console得到结果:
    this is my test

    那么我们开始打包,使用最简单的pyinstaller test1.py。打包完成后,在当前目录下有个dist文件夹,进入dist下的test1文件夹,然后打开cmd,运行这个exe,我们就会发现:

    提示: no model named ‘pymysql’

    这是怎么回事呢?那么问题来了,sqlalchemy这个库在初始化的时候是不需要显示导入引擎库的,它自己有一个create_engine()的函数来初始化,这个字符串是使用者根据规则来自己填写的。其实解决的方法很简单,我们只要在显式导入pymysql这个库即可。现在我们导入这个库:

    import pymysql
    

    重新打包一遍(重新打包的时候记得删除掉spec文件,否则会有缓存,或者是加上–clean选项清除掉),再次运行,现在就没有这个问题了。

    1. 多进程打包的问题

    官方的CPython存在一个GIL锁,这个锁的存在有很多优点,很多库都是线程安全的,单线程执行的效率也高。在python早期的一个版本中取消掉了GIL,代之以高粒度的锁来实现多线程,但是实际应用中单个线程的效率大大降低。故后来又将GIL这个锁还原回去,所以至今的python2也好还是python3中都会有这个锁。但是这个锁有很大一个问题,那就是效率问题,它导致了python仅仅只能利用一个core来进行数据的计算。所以后面为了弥补这个GIL带来的问题,专家们设计了multiprocessing库,gevent库等。前一个是多进程库,为了解决python用于数据密集型处理的情况;后一个用于异步IO处理的情况,基本原理就是在CPU时钟之间来回切换,简单的例子就是爬虫程序爬取网页的时候。假如有10个url,我们都要去GET它,实际上网络之间的延迟是大大高于计算机内部的,那么这个时间内计算机就切换到下一个。

    有时候运用多进程是必须的,这个替代不了,哪怕它占用资源很多。

    使用

    安装:

    pip install pyinstaller
    

    使用方法(例子):

    pyinstaller -D -p F:\Python27\Lib -i logo.ico mian.py
    

    -D:打包成多个文件
    -p:指定python安装包路径
    -i:指定图标,我的图标放在同目录下
    mian.py:要打包的文件,和图标放在同目录下了

    -D与-F一一对应,-F是打包成一个单独的文件。最后一排加上–noconsole,就是无窗口运行。

    如果py程序是多进程的话,使用pyinstaller打包会出现错误,这个时候只要加上一行代码

    在:
    if name==‘mian’:
    #新增
    multiprocessing.freeze_support()

    即可

    有的时候你加上图片后打包会出错,这是因为图标里面的格式出错了,需要用图片编辑软件重新对图片内部大小进行设置,这个百度一下吧~

    如果要加密混淆代码(其实没有用,一样可以反编译出你的源代码,但是聊胜于无吧)

    加上一行 --key=asfweakjhfksafkasdkdbas随便几个字符串

    好像要安装依赖包,根据提示安装即可

    cx_Freeze

    python中比较常用的python转exe方法有三种,分别是cx_freeze,py2exe,PyInstaller。py2exe恐怕是三者里面知名度最高的一个,但是同时相对来说它的打包质量恐怕也是最差的一个。pyinstaller打包很好,但是操作工序较为复杂,推荐cx_freeze,可以通过pip install cx-freeze 安装。–这是别人的描述,其实我觉得pyinstaller其实挺简单的

    使用

    安装方法:

    1. 打开cmd,输入pip install cx-freeze 后,会发现在python的Scripts文件夹下生成了三个文件
    2. 然后在cmd中,切换到Scripts路径下,输入 python cxfreeze-postinstall,会发现Scripts文件夹下又多了.bat文件,此时已经安装成功
    3. 继续在cmd下尝试输入 cxfeeeze -h 验证下,显示成功。

    提示:直接通过 pip install cx-freeze 安装,仍然出现错误时(找不到文件),最好去官网:网址手动下载相应版本的cx-freeze文件,放在Scripts文件夹下,手动双击安装,然后再运行cxfreeze-postinstall。(例如:我的python版本是3.4.3,下载cx_Freeze-4.3.3.win-amd64-py3.4的文件。注意,版本不对无法安装!)

    在cxfreeze的安装目录下即\Python34\Scripts,添加一个文件cxfreeze.bat(可用记事本)cxfreeze.bat内容如下:

    @ echo off
    C:\Python34\python.exe C:\Python34\Scripts\cxfreeze %*
    

    在该目录下输入czfreeze -h也可以查看安装情况(用pip install cxfreeze就可直接安装改第三方库)

    打包方法

    打包文件时要在Scripts文件夹路径下操作,文件的路径最好是绝对路径。例如:将 G 盘的 hello.py 打包到 G 盘的 123文件夹下:cxfreeze g:\hello.py --taget-dir g:\123 或者 cxfreeze g:\hello.py --taget-dir g:\123 --base-name=Win32GUI。加上–base-name=Win32GUI可以在运行exe时去掉cmd黑框。

    具体操作:

    首先在命令提示符中使用cd命令转换到所需要转换的python文件的目录中,因为转换后的dist文件夹会出现在命令提示符的当前目录中

    然后输入:

    cxfreeze --init-script=C:\Users\tangc\Desktop\alien_invasion\alien_invasion.py alien_invasion.py
    
    --init-script=后接绝对路径
    

    如果你的程序中有图片等资源,是需要根据程序中的相对路径加入到dist文件中,也要在.exe同目录中加入images的文件夹(图片资源)

    如果原.py程序使用了图片等素材,并且添加图片是相对路径(同一个文件夹下可以不使用绝对路径),打包文件后,需要将图片等素材拷贝一份放在打包后的文件夹下,否则运行.exe程序会找不到图片素材。

    如果原.py程序使用图片添加的是绝对路径,在本地电脑上运行时可能不会发现错误。但是你将打包后的文件发给另一台机器,运行.exe程序会报错,大概意思是“根据你写的绝对路径找不到图片等素材”,即使你在文件夹下拷贝了素材,但是绝对路径也是错误的,所以,最好使用上一种方法。

    注意:

    • 只能指定一个要打包的模块,也就是启动模块

    • 发布后,可执行文件执行路径不能有中文(最好也不要有空格)

    • 启动执行的文件中不要有下面这种判断,否则可执行文件执行会没有任何效果

        if __name__=='__mian__':
      
    • 将exe放到其他机子上运行,弹出“找不到msvcr100.dll“ ,手动将”msvcr100.dll“拷贝到dist目录下即可

    • 要去掉exe里的后面黑色控制台窗口就在前面的命令改成:
      cxfreeze C:\Users\restartRemote.py (需打包文件路径) –target-dir D:\pyproject (存放exe的目标文件夹路径)–base-name=win32gui

    nuitka

    Nuitka直接将python编译成C++代码 ,再编译C++代码产生可执行文件,完全不存在反向解析的问题,非常安全,而且由于可执行文件由C++编译而来,运行速度也会获得提升。

    但是我在打包中发现了一个文件,那就是在另一台电脑上无法运行…并且实际编译时需要近20分钟,编译的时候cpu持续100%

    不过如果只是自己的电脑上运行的话,还是挺好使的

    官方文档

    注意nuitka对python的某些语法有专门要注意的地方

    下载地址

    下载完后会提示安装编译c++代码的软件,使用的是gcc

    安装好有会有一个MinGW64的文件夹,比如我要打包一个back.py的文件,把这个py文件放在哪个目录下,常用命令如下

    python -m nuitka --recurse-all --standalone cc.py
    
    python -m nuitka --standalone back.py
    
    # 可以用的打包方式
    python -m nuitka --recurse-all --recurse-plugins=F:\Python27\Lib --remove-output --plugin-enable=enum_compat back.py
    # 带图标并且有窗口
    python -m nuitka --recurse-all --recurse-plugins=F:\Python27\Lib --remove-output --icon=logo.ico --plugin-enable=enum_compat back.py
    # 不带窗口不带图标
    python -m nuitka --recurse-all --recurse-plugins=F:\Python27\Lib --remove-output --plugin-enable=enum_compat --windows-disable-console back.py
    
    # 不删除辅助文件夹
    python -m nuitka --recurse-all --recurse-plugins=F:\Python27\Lib --icon=logo.ico --plugin-enable=enum_compat back.py
    
    # 其他可运行
    
    
    python -m nuitka --recurse-all --recurse-plugins=F:\Python27\Lib --standalone --remove-output --icon=logo.ico --plugin-enable=enum_compat back.py
    

    在编译的时候大概要挺长时间,并且cpu持续暴涨。

    速度…感觉确实变快了点…

    代码混淆

    你可以自己写混淆器,虽然说是防君子不防小人,但是…罢了不提了…

    我使用的是一个在线的代码混淆器,猜测代码会上传到那个服务器上面,所以用或不用看你的需求了

    地址

    注意:代码规范符合python3

    欢迎关注公众号:【安全研发】获取更多相关工具,课程,资料分享哦~
    在这里插入图片描述

    展开全文
  • Python 批量下载BiliBili视频 打包软件

    万次阅读 多人点赞 2020-03-08 20:31:11
    B站是一个神奇的地方,有动画、番剧,还有游戏、鬼畜,更有为广大程序猿所喜爱的科技和编程教学视频,课时你也许会为怎么下载保存下这些视频而发愁,我也遇到了这样的烦恼,于是利用强大的Python进行一番探索,实现...

    如有需要购买用于个人或公司使用的小伙伴可选择百度云或者华为云服务器,点击华为云服务器优惠链接或扫描下方二维码即可享受采购季优惠价:
    华为云采购季专属二维码

    一、项目概述

    1.项目背景

    有一天,我突然想找点事做,想起一直想学但是没有学的C语言,就决定来学一下。
    可是怎么学呢?看书的话太无聊,报班学呢又快吃土了没钱,不如去B站看看?
    果然,关键字C语言搜索,出现了很多C语言的讲课视频:
    C语言讲课视频节选
    B站https://www.bilibili.com/是一个很神奇的地方,简直就是一个无所不有的宝库,几乎可以满足你一切的需求和视觉欲。不管你是想看动画、番剧 ,还是游戏、鬼畜 ,亦或科技和各类教学视频 ,只要你能想到的,基本上都可以在B站找到。对于程序猿或即将成为程序猿的人来说,B站上的编程学习资源是学不完的,可是B站没有提供下载的功能,如果想保存下载在需要的时候看,那就是一个麻烦了。我也遇到了这个问题,于是研究怎么可以实现一键下载视频,最终用Python这门神奇的语言实现了。

    2.环境配置

    这次项目不需要太多的环境配置,最主要的是有ffmpeg(一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序)并设置环境变量就可以了。ffmpeg主要是用于将下载下来的视频和音频进行合并形成完整的视频。

    下载ffmpeg

    可点击https://download.csdn.net/download/CUFEECR/12234789或进入官网http://ffmpeg.org/download.html进行下载,并解压到你想保存的目录。

    设置环境变量

    • 复制ffmpeg的bin路径,如xxx\ffmpeg-20190921-ba24b24-win64-shared\bin
    • 此电脑右键点击属性,进入控制面板\系统和安全\系统
    • 点击高级系统设置→进入系统属性弹窗→点击环境变量→进入环境变量弹窗→选择系统变量下的Path→点击编辑点击→进入编辑环境变量弹窗
    • 点击新建→粘贴之前复制的bin路径
    • 点击确定,逐步保存退出
      动态操作示例如下:
      ffmpeg 设置环境变量

    除了ffmpeg,还需要安装pyinstaller库用于程序打包。
    可用以下命令进行安装:

    pip install pyinstaller
    

    如果遇到安装失败或下载速度较慢,可换源:

    pip install pyinstaller -i https://pypi.doubanio.com/simple/
    

    二、项目实施

    1.导入需要的库

    import json
    import os
    import re
    import shutil
    import ssl
    import time
    import requests
    from concurrent.futures import ThreadPoolExecutor
    from lxml import etree
    

    导入的库包括用于爬取和解析网页的库,还包括创建线程池的库和进行其他处理的库,大多数都是Python自带的,如有未安装的库,可使用pip install xxx命令进行安装。

    2.设置请求参数

    # 设置请求头等参数,防止被反爬
    headers = {
        'Accept': '*/*',
        'Accept-Language': 'en-US,en;q=0.5',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36'
    }
    params = {
        'from': 'search',
        'seid': '9698329271136034665'
    }
    

    设置请求头等参数,减少被反爬的可能。

    3.基本处理

    def re_video_info(text, pattern):
        '''利用正则表达式匹配出视频信息并转化成json'''
        match = re.search(pattern, text)
        return json.loads(match.group(1))
    
    
    def create_folder(aid):
        '''创建文件夹'''
        if not os.path.exists(aid):
            os.mkdir(aid)
    
    
    def remove_move_file(aid):
        '''删除和移动文件'''
        file_list = os.listdir('./')
        for file in file_list:
            # 移除临时文件
            if file.endswith('_video.mp4'):
                os.remove(file)
                pass
            elif file.endswith('_audio.mp4'):
                os.remove(file)
                pass
            # 保存最终的视频文件
            elif file.endswith('.mp4'):
                if os.path.exists(aid + '/' + file):
                    os.remove(aid + '/' + file)
                shutil.move(file, aid)
    

    主要包括两方面的基本处理,为正式爬取下载做准备:

    • 利用正则表达式提取信息
      通过requests库请求得到请求后的网页,属于文本,通过正则表达式提取得到关于将要下载的视频的有用信息,便于后一步处理。
    • 文件处理
      将下载视频完成后的相关文件进行处理,包括删除生成的临时的音视频分离的文件和移动最终视频文件到指定文件夹。

    4.下载视频

    def download_video_batch(referer_url, video_url, audio_url, video_name, index):
        '''批量下载系列视频'''
        # 更新请求头
        headers.update({"Referer": referer_url})
        # 获取文件名
        short_name = video_name.split('/')[2]
        print("%d.\t视频下载开始:%s" % (index, short_name))
        # 下载并保存视频
        video_content = requests.get(video_url, headers=headers)
        print('%d.\t%s\t视频大小:' % (index, short_name),
              round(int(video_content.headers.get('content-length', 0)) / 1024 / 1024, 2), '\tMB')
        received_video = 0
        with open('%s_video.mp4' % video_name, 'ab') as output:
            headers['Range'] = 'bytes=' + str(received_video) + '-'
            response = requests.get(video_url, headers=headers)
            output.write(response.content)
        # 下载并保存音频
        audio_content = requests.get(audio_url, headers=headers)
        print('%d.\t%s\t音频大小:' % (index, short_name),
              round(int(audio_content.headers.get('content-length', 0)) / 1024 / 1024, 2), '\tMB')
        received_audio = 0
        with open('%s_audio.mp4' % video_name, 'ab') as output:
            headers['Range'] = 'bytes=' + str(received_audio) + '-'
            response = requests.get(audio_url, headers=headers)
            output.write(response.content)
            received_audio += len(response.content)
        return video_name, index
    
    
    def download_video_single(referer_url, video_url, audio_url, video_name):
        '''单个视频下载'''
        # 更新请求头
        headers.update({"Referer": referer_url})
        print("视频下载开始:%s" % video_name)
        # 下载并保存视频
        video_content = requests.get(video_url, headers=headers)
        print('%s\t视频大小:' % video_name, round(int(video_content.headers.get('content-length', 0)) / 1024 / 1024, 2), '\tMB')
        received_video = 0
        with open('%s_video.mp4' % video_name, 'ab') as output:
            headers['Range'] = 'bytes=' + str(received_video) + '-'
            response = requests.get(video_url, headers=headers)
            output.write(response.content)
        # 下载并保存音频
        audio_content = requests.get(audio_url, headers=headers)
        print('%s\t音频大小:' % video_name, round(int(audio_content.headers.get('content-length', 0)) / 1024 / 1024, 2), '\tMB')
        received_audio = 0
        with open('%s_audio.mp4' % video_name, 'ab') as output:
            headers['Range'] = 'bytes=' + str(received_audio) + '-'
            response = requests.get(audio_url, headers=headers)
            output.write(response.content)
            received_audio += len(response.content)
        print("视频下载结束:%s" % video_name)
        video_audio_merge_single(video_name)
    

    这部分包括系列视频的批量下载和单个视频的下载,两者的大体实现原理近似,但是由于两个函数的参数有差别,因此分别实现。
    在具体的实现中,首先更新请求头,请求视频链接并保存视频(无声音),再请求音频链接并保存音频,在这个过程中得到相应的视频和音频文件的大小。

    5.视频和音频合并成完整的视频

    def video_audio_merge_batch(result):
        '''使用ffmpeg批量视频音频合并'''
        video_name = result.result()[0]
        index = result.result()[1]
        import subprocess
        video_final = video_name.replace('video', 'video_final')
        command = 'ffmpeg -i "%s_video.mp4" -i "%s_audio.mp4" -c copy "%s.mp4" -y -loglevel quiet' % (
            video_name, video_name, video_final)
        subprocess.Popen(command, shell=True)
        print("%d.\t视频下载结束:%s" % (index, video_name.split('/')[2]))
    
    
    def video_audio_merge_single(video_name):
        '''使用ffmpeg单个视频音频合并'''
        print("视频合成开始:%s" % video_name)
        import subprocess
        command = 'ffmpeg -i "%s_video.mp4" -i "%s_audio.mp4" -c copy "%s.mp4" -y -loglevel quiet' % (
            video_name, video_name, video_name)
        subprocess.Popen(command, shell=True)
        print("视频合成结束:%s" % video_name)
    

    这个过程也是批量和单个分开,大致原理差不多,都是调用subprogress模块生成子进程,Popen类来执行shell命令,由于已经将ffmpeg加入环境变量,所以shell命令可以直接调用ffmpeg来合并音视频。

    6.3种下载方式的分别实现

    def batch_download():
        '''使用多线程批量下载视频'''
        # 提示输入需要下载的系列视频对应的id
        aid = input('请输入要下载的视频id(举例:链接https://www.bilibili.com/video/av91748877?p=1中id为91748877),默认为91748877\t')
        if aid:
            pass
        else:
            aid = '91748877'
        # 提示选择清晰度
        quality = input('请选择清晰度(1代表高清,2代表清晰,3代表流畅),默认高清\t')
        if quality == '2':
            pass
        elif quality == '3':
            pass
        else:
            quality = '1'
        acc_quality = int(quality) - 1
        # ssl模块,处理https请求失败问题,生成证书上下文
        ssl._create_default_https_context = ssl._create_unverified_context
        # 获取视频主题
        url = 'https://www.bilibili.com/video/av{}?p=1'.format(aid)
        html = etree.HTML(requests.get(url, params=params, headers=headers).text)
        title = html.xpath('//*[@id="viewbox_report"]/h1/span/text()')[0]
        print('您即将下载的视频系列是:', title)
        # 创建临时文件夹
        create_folder('video')
        create_folder('video_final')
        # 定义一个线程池,大小为3
        pool = ThreadPoolExecutor(3)
        # 通过api获取视频信息
        res_json = requests.get('https://api.bilibili.com/x/player/pagelist?aid={}'.format(aid)).json()
        video_name_list = res_json['data']
        print('共下载视频{}个'.format(len(video_name_list)))
        for i, video_content in enumerate(video_name_list):
            video_name = ('./video/' + video_content['part']).replace(" ", "-")
            origin_video_url = 'https://www.bilibili.com/video/av{}'.format(aid) + '?p=%d' % (i + 1)
            # 请求视频,获取信息
            res = requests.get(origin_video_url, headers=headers)
            # 解析出视频详情的json
            video_info_temp = re_video_info(res.text, '__playinfo__=(.*?)</script><script>')
            video_info = {}
            # 获取视频品质
            quality = video_info_temp['data']['accept_description'][acc_quality]
            # 获取视频时长
            video_info['duration'] = video_info_temp['data']['dash']['duration']
            # 获取视频链接
            video_url = video_info_temp['data']['dash']['video'][acc_quality]['baseUrl']
            # 获取音频链接
            audio_url = video_info_temp['data']['dash']['audio'][acc_quality]['baseUrl']
            # 计算视频时长
            video_time = int(video_info.get('duration', 0))
            video_minute = video_time // 60
            video_second = video_time % 60
            print('{}.\t当前视频清晰度为{},时长{}分{}秒'.format(i + 1, quality, video_minute, video_second))
            # 将任务加入线程池,并在任务完成后回调完成视频音频合并
            pool.submit(download_video_batch, origin_video_url, video_url, audio_url, video_name, i + 1).add_done_callback(
                video_audio_merge_batch)
        pool.shutdown(wait=True)
        time.sleep(5)
        # 整理视频信息
        if os.path.exists(title):
            shutil.rmtree(title)
        os.rename('video_final', title)
        try:
            shutil.rmtree('video')
        except:
            shutil.rmtree('video')
    
    
    def multiple_download():
        '''批量下载多个独立视频'''
        # 提示输入所有aid
        aid_str = input(
            '请输入要下载的所有视频id,id之间用空格分开\n举例:有5个链接https://www.bilibili.com/video/av89592082、https://www.bilibili.com/video/av68716174、https://www.bilibili.com/video/av87216317、\nhttps://www.bilibili.com/video/av83200644和https://www.bilibili.com/video/av88252843,则输入89592082 68716174 87216317 83200644 88252843\n默认为89592082 68716174 87216317 83200644 88252843\t')
        if aid_str:
            pass
        else:
            aid_str = '89592082 68716174 87216317 83200644 88252843'
        if os.path.exists(aid_str):
            shutil.rmtree(aid_str)
        aids = aid_str.split(' ')
        # 提示选择视频质量
        quality = input('请选择清晰度(1代表高清,2代表清晰,3代表流畅),默认高清\t')
        if quality == '2':
            pass
        elif quality == '3':
            pass
        else:
            quality = '1'
        acc_quality = int(quality) - 1
        # 创建文件夹
        create_folder(aid_str)
        # 创建线程池,执行多任务
        pool = ThreadPoolExecutor(3)
        for aid in aids:
            # 将任务加入线程池
            pool.submit(single_download, aid, acc_quality)
        pool.shutdown(wait=True)
        time.sleep(5)
        # 删除临时文件,移动文件
        remove_move_file(aid_str)
    
    
    def single_download(aid, acc_quality):
        '''单个视频实现下载'''
        # 请求视频链接,获取信息
        origin_video_url = 'https://www.bilibili.com/video/av' + aid
        res = requests.get(origin_video_url, headers=headers)
        html = etree.HTML(res.text)
        title = html.xpath('//*[@id="viewbox_report"]/h1/span/text()')[0]
        print('您当前正在下载:', title)
        video_info_temp = re_video_info(res.text, '__playinfo__=(.*?)</script><script>')
        video_info = {}
        # 获取视频质量
        quality = video_info_temp['data']['accept_description'][acc_quality]
        # 获取视频时长
        video_info['duration'] = video_info_temp['data']['dash']['duration']
        # 获取视频链接
        video_url = video_info_temp['data']['dash']['video'][acc_quality]['baseUrl']
        # 获取音频链接
        audio_url = video_info_temp['data']['dash']['audio'][acc_quality]['baseUrl']
        # 计算视频时长
        video_time = int(video_info.get('duration', 0))
        video_minute = video_time // 60
        video_second = video_time % 60
        print('当前视频清晰度为{},时长{}分{}秒'.format(quality, video_minute, video_second))
        # 调用函数下载保存视频
        download_video_single(origin_video_url, video_url, audio_url, title)
    
    
    def single_input():
        '''单个文件下载,获取参数'''
        # 获取视频aid
        aid = input('请输入要下载的视频id(举例:链接https://www.bilibili.com/video/av89592082中id为89592082),默认为89592082\t')
        if aid:
            pass
        else:
            aid = '89592082'
            # 提示选择视频质量
        quality = input('请选择清晰度(1代表高清,2代表清晰,3代表流畅),默认高清\t')
        if quality == '2':
            pass
        elif quality == '3':
            pass
        else:
            quality = '1'
        acc_quality = int(quality) - 1
        # 调用函数进行下载
        single_download(aid, acc_quality)
    

    在一般情形下,下载的需求包含3种情况:

    • 单个视频的下载
      只有一个视频,没有和它属于同一个系列的其他视频,如下图
      单个视频下载
      此时,除了右下方的相关推荐中的视频,没有其他视频,右上方只有弹幕列表、没有视频列表。为了代码的复用,将单个视频下载时提示用户输入需求的代码单独提取出来作为single_input(),下载的函数另外作为single_download(aid, acc_quality)函数实现,在该函数中:
      通过视频链接如https://www.bilibili.com/video/av89592082解析网页,得到相应的字符串并转化成json,如下:
      视频信息json转化
      字符串json格式化可使用https://www.sojson.com/editor.html进行在线转化。
      获取到视频的标题、根据输入确定的视频质量、持续时长、视频链接和音频链接,并调用download_video_single()函数下载该视频。
    • 多个视频的下载
      这里,多个视频之间是没有关系的,多个视频的下载实际上是先获取到所有的aid,并进行循环,对每个视频链接传入参数调用单个视频下载的函数即可。同时设立线程池,大小为3,既不会对资源有太大的要求,也能实现多任务、提高下载效率。
    • 系列视频的下载
      此时,多个视频属于同一系列,如https://www.bilibili.com/video/av91748877是一个课程系列,如下
      系列视频
      显然,此时右上方有视频列表,标明了有65个子视频,每个视频用p标识,如第2个视频就是https://www.bilibili.com/video/av91748877?p=2。对于所有视频,先获取到视频的相关信息,再加入进程池进行下载,并在任务结束之后回调函数video_audio_merge_batch()合并音视频,并进行文件整理。

    7.主函数

    def main():
        '''主函数,提示用户进行三种下载模式的选择'''
        download_choice = input('请输入您需要下载的类型:\n1代表下载单个视频,2代表批量下载系列视频,3代表批量下载多个不同视频,默认下载单个视频\t')
        # 批量下载系列视频
        if download_choice == '2':
            batch_download()
        # 批量下载多个单个视频
        elif download_choice == '3':
            multiple_download()
        # 下载单个视频
        else:
            single_input()
    
    
    if __name__ == '__main__':
        '''调用主函数'''
        main()
    

    主函数中实现3种下载方式对应的函数的分别调用。

    三、项目分析和说明

    1.结果测试

    对3种方式进行测试的效果如下:

    project test 1
    project test 2
    project test 3
    3种下载情景的测试效果均较好,下载速度也能与一般的下载速度相媲美。
    代码可点击https://download.csdn.net/download/CUFEECR/12243122https://github.com/corleytd/Python_Crawling/blob/master/bilibili_downloader_1.py进行下载。

    改进说明

    B站网站也一直在变化,所以对于下载可能也会有一些变化,所以将改进的地方在下面列举出来:

    • 网址参数变化
      举例说明:
      这段时间发现B站一个视频系列的链接变成https://www.bilibili.com/video/BV1x7411M74h?p=65,即是无规律的字符串(可能是经过某种算法编码或加密得到的),现在从链接中不能得到视频(系列)的aid,这时候可以借助浏览器工具抓包查看数据来找到该视频的aid,如下:
      aid2bvid
      在左侧寻找stat开头的请求,后边的参数即为aid,该请求api的完整链接为https://api.bilibili.com/x/web-interface/archive/stat?aid=91748877,所以可以直接在该链接中获取aid,也可以查看该请求的具体内容,可以看到第一个数据就是aid,我们也可以看到随机字符串就是bvid,可能是建立了aid和bvid的一一映射,找到aid就可以正常下载了。

    2.软件打包

    在命令行中,使路径位于代码所在路径运行

    pyinstaller bilibili_downloader_1.py
    

    打印

    136 INFO: PyInstaller: 3.6
    137 INFO: Python: 3.7.4
    138 INFO: Platform: Windows-10-10.0.18362-SP0
    140 INFO: wrote xxxx\Bili_Video_Batch_Download\bilibili_downloader_1.spec
    205 INFO: UPX is not available.
    209 INFO: Extending PYTHONPATH with paths
    ['xxxx\\Bili_Video_Batch_Download',
     'xxxx\\Bili_Video_Batch_Download']
    210 INFO: checking Analysis
    211 INFO: Building Analysis because Analysis-00.toc is non existent
    211 INFO: Initializing module dependency graph...
    218 INFO: Caching module graph hooks...
    247 INFO: Analyzing base_library.zip ...
    5499 INFO: Caching module dependency graph...
    5673 INFO: running Analysis Analysis-00.toc
    5702 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable
      required by xxx\python\python37\python.exe
    6231 INFO: Analyzing xxxx\Bili_Video_Batch_Download\bilibili_downloader_1.py
    7237 INFO: Processing pre-safe import module hook   urllib3.packages.six.moves
    10126 INFO: Processing pre-safe import module hook   six.moves
    14287 INFO: Processing module hooks...
    14288 INFO: Loading module hook "hook-certifi.py"...
    14296 INFO: Loading module hook "hook-cryptography.py"...
    14936 INFO: Loading module hook "hook-encodings.py"...
    15093 INFO: Loading module hook "hook-lxml.etree.py"...
    15097 INFO: Loading module hook "hook-pydoc.py"...
    15099 INFO: Loading module hook "hook-xml.py"...
    15330 INFO: Looking for ctypes DLLs
    15334 INFO: Analyzing run-time hooks ...
    15339 INFO: Including run-time hook 'pyi_rth_multiprocessing.py'
    15344 INFO: Including run-time hook 'pyi_rth_certifi.py'
    15355 INFO: Looking for dynamic libraries
    15736 INFO: Looking for eggs
    15737 INFO: Using Python library xxx\python\python37\python37.dll
    15757 INFO: Found binding redirects:
    []
    15776 INFO: Warnings written to xxxx\Bili_Video_Batch_Download\build\bilibili_downloader_1\war
    n-bilibili_downloader_1.txt
    15942 INFO: Graph cross-reference written to xxxx\Bili_Video_Batch_Download\build\bilibili_dow
    nloader_1\xref-bilibili_downloader_1.html
    15967 INFO: checking PYZ
    15968 INFO: Building PYZ because PYZ-00.toc is non existent
    15968 INFO: Building PYZ (ZlibArchive) xxxx\Bili_Video_Batch_Download\build\bilibili_downloade
    r_1\PYZ-00.pyz
    16944 INFO: Building PYZ (ZlibArchive) xxxx\Bili_Video_Batch_Download\build\bilibili_downloade
    r_1\PYZ-00.pyz completed successfully.
    16980 INFO: checking PKG
    16981 INFO: Building PKG because PKG-00.toc is non existent
    16981 INFO: Building PKG (CArchive) PKG-00.pkg
    17030 INFO: Building PKG (CArchive) PKG-00.pkg completed successfully.
    17034 INFO: Bootloader xxx\python\python37\lib\site-packages\PyInstaller\bootloader\Windows-64bit\run.exe
    17034 INFO: checking EXE
    17035 INFO: Building EXE because EXE-00.toc is non existent
    17035 INFO: Building EXE from EXE-00.toc
    17037 INFO: Appending archive to EXE xxxx\Bili_Video_Batch_Download\build\bilibili_downloader_
    1\bilibili_downloader_1.exe
    17046 INFO: Building EXE from EXE-00.toc completed successfully.
    17053 INFO: checking COLLECT
    17053 INFO: Building COLLECT because COLLECT-00.toc is non existent
    17055 INFO: Building COLLECT COLLECT-00.toc
    

    出现INFO: Building EXE from EXE-00.toc completed successfully. 即打包成功。
    在当前路径下找到distbuild目录下的bilibili_downloader_1目录下的bilibili_downloader_1.exe,即是打包后的软件。
    点击打开即可进行选择和输入,开始下载相应视频。
    测试示例如下:
    project test 4
    bilibili_downloader_1.exe的同级目录下可以看到下载保存的视频。

    3.改进分析

    该项目是小编进行B站视频下载的首次尝试,难免有很多不足,在实现的过程中和后期的总结中,可以看出还存在一些问题:

    • 还不能下载B站上的所有视频,目前局限于各种普通视频教程,不能下载直播视频、大会员番剧等,可以在后期进一步优化;
    • 代码过于繁琐,有不少功能类似的重复代码,可以进一步简化、提高代码的复用性;
    • 没有采取适当的措施应对B站的反爬,可能会因为请求过多而无法正常下载。
      可以在后期进行优化,使整个程序更加健壮。

    4.合法性说明

    • 本项目的出发点是方便地下载B站上的学习视频,可以更好地学习各类教程,这对程序猿来说也是一种福利,但是绝不用与其他商业目的,所有读者可以参考执行思路和程序代码,但不能用于恶意和非法目的(恶意频繁下载视频、非法盈利等),如有违者请自行负责。
    • 本项目在实施的过程中可能参考了其他大佬的实现思路,如有侵犯他人利益,请联系更改或删除。
    • 本项目是B站视频批量下载系列的第一篇,有很多尚待改进的地方,后期会继续更新,欢迎各位读者交流指正,以期不断改进。
    展开全文
  • 二、使用pyinstaller打包Python程序 ①在你的Python程序文件夹上(不点进去)按住shift并且右键,在弹出的选项中点击"打开PowerShell窗口” ②输入以下指令,开始打包 pyinstaller -F -w (-i icofile) filename ...

    一、安装pyinsatller

    打开命令行窗口,输入如下指令

    pip3 install pyinstaller

    二、使用pyinstaller打包Python程序

    ①在你的Python程序文件夹上(不点进去)按住shift并且右键,在弹出的选项中点击"打开PowerShell窗口”
    在这里插入图片描述②输入以下指令,开始打包

    pyinstaller -F -w (-i icofile) filename

    filename表示你的Python程序文件名

    -w 表示隐藏程序运行时的命令行窗口(不加-w会有黑色窗口)

    括号内的为可选参数,-i icofile表示给程序加上图标,图标必须为.ico格式

    icofile表示图标的位置,建议直接放在程序文件夹里面,这样子打包的时候直接写文件名就好

    输入完成,按回车,就会开始自动打包了,第一次打包过程可能比较缓慢

    输入示例:

    pyinstaller -F -w -i favicon webank.py

    打包好的软件在dist目录下
    在这里插入图片描述

    展开全文
  • python 打包工具

    2017-07-06 18:15:41
    本工具是对pyinstaller的可视化封装,提供图形界面操作,填写参数即可将Python程序打包成单文件或者单目录的可执行程序
  • 此时如果我们能给别人一个exe软件直接双击运行就好多了,那么就需要用到今天介绍的python程序打包工具pyinstaller了。 1、安装pyinstaller 首先安装pyinstaller,使用安装命令: pip install pyinstaller 2、打包...

    需求:我们需要把自己使用python开发好的程序发给朋友体验一下
    这就需要让朋友安装python的解释器,安装程序所需要的python包,最最最重要的是还要考虑版本兼容问题,特别麻烦。
    此时如果我们能给别人一个exe软件直接双击运行就好多了,那么就需要用到今天介绍的python程序打包工具pyinstaller了。

    1、安装pyinstaller

    首先安装pyinstaller,使用安装命令:

    pip install pyinstaller
    

    在这里插入图片描述

    2、打包程序

    我们写的python脚本是不能脱离python解释器单独运行的,所以在打包的时候,至少会将python解释器和脚本一起打包,同样,为了打包的exe能正常运行,会把我们所有安装的第三方包一并打包到exe。

    PyInstaller 工具的命令语法如下:

    pyinstaller 选项 main.py
    

    不管这个 Python 应用是单文件的应用,还是多文件的应用,只要在使用 pyinstaller 命令时编译作为程序入口的 Python 程序即可。

    2.1、进入当前文件所在目录

    在这里插入图片描述

    2.2、执行打包命令

    pyinstaller -F 智能闲聊.py
    

    在这里插入图片描述
    执行上面命令,将看到详细的生成过程。当生成完成后,将会在此目录下看到多了一个 dist 目录,并在该目录下看到有一个 智能闲聊.exe 文件,这就是使用 PyInstaller 工具生成的 EXE 程序。
    在这里插入图片描述

    展开全文
  • 开发环境: 系统:Windows10 Python环境:Anaconda集成开发环境 Python版本:3.8 在正式讲解本文之前,我们先来谈谈为什么要对Python程序打包?...目前网上能获取的免费的Python打包工具主要有三种:
  • 摘要:Python 打包程序,制作实用天气查询软件。作者 | flywind来源 | Pyhton高效编程通常我们查询天气都是在 App 或者网页中搜索,其实这点事儿 P...
  • python打包发布

    2019-08-23 14:58:11
    1.安装pyinstaller pip install pyinstaller 2.命令语法 pyinstaller 选项 python源文件 常用选项: ...-F:产生单个可执行文件。...-D:产生一个目录,包含多个...首先跳转到xxx软件目录下,执行:pyinstaller -...
  • python打包app问题

    2020-08-25 10:36:54
    操作步骤:按照python打包 中用py2app打包方式对dialog.app进行打包。 操作结果:打开setup.py 时出现该报错信息 A Python runtime not could be located. You may need to install a framework build of Python, or...
  • Python软件封装打包

    千次阅读 2020-01-11 16:02:25
    作者:Naples ...来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业...Python Tkinter打包封装的方法有:PyInstaller, py2exe, wxPython等方法。答主只是用了PyInstaller来打包,感觉特别好用,对其...
  • Python打包成exe

    2018-11-12 22:03:55
    Python打包成exe
  • python 打包工具对比

    千次阅读 2019-10-28 15:29:46
    python打包工具对比: 基本需求:1-支持linux系统; 2-可生成独立文件,不再依赖任何第三方库,便于发布; 常用的一些工具有: 工具名称 windows linux 是否支持单文件模式 bbfreeze yes yes no...
  • 最近由很多人私聊小编问如何将python脚本打包成10多M的? 那今天小编就给大家全面总结一下:Python如何打包成exe,以及如何打得足够小。 标准打包 目前比较常见的打包exe方法都是通过Pyinstaller来实现的,本文也...
  • Python 打包指南

    2012-06-16 23:39:34
    一个成功的开源项目的其核心功能是打包功能,而出色的打包功能的关键在于版本控制。因为项目是开源的,所以您希望发布的包能够体现出开源社区所具备...除了正确做法这条理由之外,打包软件还有三条实际的理由: 易用
  • Qt for Python Mac下使用 fbs 打包软件

    千次阅读 2019-08-14 22:28:51
    Python打包工具 Python的常用的打包工具包括:fbs、PyInstaller、cx_Freeze、py2exe、py2app,而Qt for Python是一个跨平台的框架,因此我们希望专注于在Qt支持的三个主要平台上运行的解决方案:Linux,macOS和...
  • python打包工具比较

    千次阅读 2016-08-24 16:04:44
    前一段用python写了点小工具,希望能给同事用,这里总结一下python打包以及构建的方法。首先是一些需要安装依赖包的方法,这也是比较推荐的正统的方法。1.setuptools or pip 在setup.py文件中写明依赖的库和版本...
  • Python软件打包成EXE文件

    万次阅读 2020-07-13 23:26:55
    我们写好一个Python程序,给同行只需要将代码发个对方,但是要是给一个根本不需要学习python人员,难道我们还帮对方安装一个Python的环境吗? 当然不需要! 话不多说,看干货。 第一步:安装pyinstaller pip...
  • python打包指南

    2015-01-15 21:21:20
    最佳开源 Python 应用程序通常会提供出色的打包功能。 我们首先将了解有关什么是打包及其基本实现的详细信息。然后更进一步探索与打包相关的版本控制与发布工作。 一个成功的开源项目的其核心功能是打包功能,而...
  • Python项目打包发布方法

    万次阅读 多人点赞 2018-12-29 11:56:07
    目前python打包工具有多个,目前比较好用的为pyinstaller,该工具可以支持在window和linux下使用。 在windows下,大小为几十K的源文件打包成exe文件,可能为几十兆,原因是把程序所引用的库文件也一起打包在一起。...
  • Python打包EXE程序

    2019-02-20 15:01:39
    最近用Python,想做一个服务器和客户端的软件,原来一直是在客户端直接起Python脚本,感觉不够灵活,尤其是运行Python脚本,还要搭建环境,查资料发现Python是支持打包EXE程序的 ...
  • 打包发布qt+python软件

    2021-06-03 12:54:54
    最近开发了一款可视化软件平台,初次接触Qt,在这里简单记录一下软件(Qt+Python)的打包过程。 对于qt的依赖库,qt提供了windeployqt.exe来进行打包
  • python打包exe记录

    2020-04-20 00:53:33
    因个人需要尝试把pyqt开发的小软件打包成exe给别人使用,网上搜了下打包很简单,就一行代码,但是暗坑比较多,特此记录。 首先pip install pyinstaller,一定要安装在软件依赖的环境中 pyinstaller [参数] [要...
  • Python打包whl文件

    2020-07-23 14:50:51
    1.检查 python setup.py check 2.打包 python setup.py sdist bdist_wheel || true
  • 在我们完成一个Python项目或一个程序时,希望将Python的py文件打包成在Windows系统下直接可以运行的exe程序。在浏览网上的资料来看,有利用pyinstaller和cx_Freeze进行打包的方法。关于cx_Freeze打包的方法,可以...
  • 如何将python3.6软件的py文件打包成exe程序?这里总结了如何将写好的python程序进行打包成exe程序,方便把自己写好的东西提供给他人用,只针对python3.6版本。
  • 如何将python3.6软件的py文件打包成exe程序

    万次阅读 多人点赞 2017-09-09 20:07:42
    在我们完成一个Python项目或一个程序时,希望将Python的py文件打包成在Windows系统下直接可以运行的exe程序。在浏览网上的资料来看,有利用pyinstaller和cx_Freeze进行打包的方法。关于cx_Freeze打包的方法,可以...
  • 主要介绍了将Python代码打包为jar软件的简单方法,一些情况下会有利于Python和Java项目之间的协作,需要的朋友可以参考下
  • 使用python编写脚本,需要发给别人使用的时候,总会想到如何打包成exe文件,发给对方。这样的话,对方可以直接使用运行,无需安装python。所以看网上的教程,大多使用pyinstaller。以下介绍下安装方法: 1、在cmd...
  • 关于python打包成exe

    2017-04-18 16:01:43
    要做Python打包成exe,在网上看到别人的经验,自己照着做了一下,记录一下我的操作流程 首先选择pyInstaller是一款用于将pyhon程序打包成exe文件的工具,pyInstaller不是一个python的包, 只需要把pyInstaller的...
  • 别再问我Python打包成exe了!(终极版)

    千次阅读 多人点赞 2021-01-13 13:01:00
    大家好,我是小五????《老板又出难题,气得我写了个自动化软件》上次这篇文章中,评论区有好几条留言都是关心如何将python脚本打包成10多M的?那今天小五就给大家全面总结一下:Pyth...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 39,687
精华内容 15,874
关键字:

python打包软件

python 订阅