吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2548|回复: 16
上一主题 下一主题
收起左侧

[Python 原创] 用Python下载小破站视频

[复制链接]
跳转到指定楼层
楼主
QuiryRain 发表于 2023-1-10 18:08 回帖奖励
本帖最后由 QuiryRain 于 2023-2-15 22:14 编辑

原因:前两天一朋友问有没有小破站的视频下载工具。然后就想着,最近学了点python是不是可以实现。

新增:
    1. 视频以当前最高清晰度进行下载,在带上cookie的前提下,可下载大会员视频。
    2. 增加音轨、视频轨下载进度条

原理: 下载视频轨道文件、和音频轨道文件,最后用ffmpeg进行视频轨和音轨的合成

目前下载工具可以在 win/linux/mac上运行。其实就是执行python

Linux/Mac OS X

在linux/Mac OS X系统中可能需要修改下文件权限

Linux

cd /path/to/BiliDown
chmod +x tools/linux/ffmpeg  

Mac

cd /path/to/BiliDown
chmod +x tools/mac/ffmpeg  

教程

pip install -r reqirements.txt

编辑 download.py 文件,在最后 url 中填上你需要下载的B站链接,
如果需要换 cookie, 在Cookies中填写你浏览器中的cookie内容
最后用python执行就行了

最终需要的视频会在当前目录下的 Output 中生成


代码:
[Python] 纯文本查看 复制代码
#!/usr/bin/env python3
# -*- coding: utf8 -*-
import os
import sys
import re
import time
import platform
import json
import traceback
import requests
import subprocess

requests.packages.urllib3.disable_warnings()

sess = requests.Session()
sess.headers.update({
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',

})

def CMD(command):
    p = subprocess.Popen(command, shell=True, universal_newlines=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE, encoding='utf8')
    stdout, stderr = p.communicate(timeout=10)
    stdout = stdout.strip()
    return stdout, stderr

def download_file(filename, url):
    resp = sess.get(url, verify=False, stream=True)
    content_size = int(resp.headers['content-length'])
    if resp.status_code != 200:
        print('请求失败')
        sys.exit()
    size = 0
    start_time = time.time()
    print('Downloading ... File Size: {size:.2f} MB'.format(size=content_size/1024/1024.0))
    with open(filename, 'wb') as f:
        for chunk in resp.iter_content(chunk_size=1024):
            if chunk:
                f.write(chunk)
                size += len(chunk)
                print(
                    '\r[下载进度]: %s %.2f%%' % (
                        '>'*int(size*50 / content_size),
                        float(size / content_size * 100)),
                    end=' ')
    print('\nDownload completed!,times: {}秒'.format(int(time.time() - start_time)))
    return filename


def delete_cache_file(path):
    try:
        os.remove(path)
    except Exception as e:
        print(e)


def get_video_and_audio_url_from_bilibili(url):
    re_playinfo = re.compile(r'window\.__playinfo__=(\{.*?)</script>', re.I)
    re_initial_state = re.compile(r'window\.__INITIAL_STATE__=(\{.*?);\(function\(\)', re.I)

    sess.headers.update({'referer': url})
    resp = sess.get(url, verify=False, timeout=(8, 8))
    html = resp.text
    # print(html)

    _initial_state = re_initial_state.search(html)
    _playinfo = re_playinfo.search(html)
    if not all([_initial_state, _playinfo]):
        print('请求失败')
        sys.exit()

    playinfo = _playinfo.group(1)
    playinfo_json = json.loads(playinfo)
    initial_state = _initial_state.group(1)
    initial_state_json = json.loads(initial_state)
    dash = playinfo_json.get('data', {}).get('dash', {})
    video_urls = []
    for video in dash.get('video', []):
        base_url = video.get('baseUrl', '')
        if not base_url:
            continue
        video_urls.append(base_url)

    audio_urls = []
    for audio in dash.get('audio', []):
        base_url = audio.get('baseUrl')
        if not base_url:
            continue
        audio_urls.append(base_url)

    title = (initial_state_json.get('h1Title')
             or initial_state_json.get('videoData', {}).get('title')
             or get_bvid(url))
    return video_urls, audio_urls, title


def create_cache_directory():
    if not os.path.exists('BVcache'):
        os.mkdir('BVcache')

    if not os.path.exists('Output'):
        os.mkdir('Output')


def get_bvid(url):
    create_cache_directory()
    return url.split('?')[0].rsplit('/', maxsplit=1)[1]


def main(url):
    bvid = get_bvid(url)

    video_urls, audio_urls, video_name = get_video_and_audio_url_from_bilibili(url)
    # print(video_urls, audio_urls)

    video_filename = f'BVcache/video_{bvid}.m4s'
    audio_filename = f'BVcache/audio_{bvid}.m4s'
    print(f'{video_name}: {bvid} 开始下载视频轨道数据...')
    for video_url in video_urls:
        try:
            download_file(video_filename, video_url)
            break
        except Exception as e:
            print('Video Error. {}'.format(e))
            print(traceback.format_exc())
    print(f'{video_name}: {bvid} 视频轨道下载完毕')
    print(f'{video_name}: {bvid} 开始下载音频轨道数据...')
    for audio_url in audio_urls:
        try:
            download_file(audio_filename, audio_url)
            break
        except Exception as e:
            print('Audio Error. {}'.format(e))
    print(f'{video_name}: {bvid} 音频轨道下载完毕!')

    system = (platform.platform()).lower()
    if 'windows' in system:
        ffmpeg_tool = r'.\tools\win\ffmpeg.exe'
    elif 'macOS' in system:
        ffmpeg_tool = './tools/mac/ffmpeg'
    else:
        ffmpeg_tool = './tools/linux/ffmpeg'
    filename = video_name.replace(" ", "-") or bvid
    ffmpeg_command = (
        ffmpeg_tool + f' -i {video_filename} -i {audio_filename} -codec '
                      f'copy Output/{filename}.mp4'
    )
    # print(ffmpeg_command)

    CMD(ffmpeg_command)

    delete_cache_file(video_filename)
    delete_cache_file(audio_filename)

    print(f'{bvid} 视频mp4文件已经生成,请在当前运行路径中的"Output"文件夹中查看,'
          f'生成的文件名称为: {filename}.mp4')


if __name__ == '__main__':
    # url = 'https://www.bilibili.com/video/BV1yr4y1r7f6?spm_id_from=333.851.b_7265636f6d6d656e64.5'

    url = "https://www.bilibili.com/bangumi/play/ep706667?spm_id_from=333.337.0.0"
    # url = "https://www.bilibili.com/video/BV1Px4y1G7Ua"
    # url = 'https://www.bilibili.com/bangumi/play/ss44096?theme=movie&from_spmid=666.7.hotlist.2'
    url = 'https://www.bilibili.com/bangumi/play/ss41936?from_spmid=666.23.0.0'
    url = 'https://www.bilibili.com/bangumi/play/ep468228?from_spmid=666.25.episode.0&from_outer_spmid=666.24.0.0'
    sess.headers.update({
        # 'cookie': ("Your Cookie")
    })
    main(url)

    """
    运行环境: Linux、python
    安装环境包:pip install requests
    将上面的url修改为要下载的视频地址。
    运行:python download.py
    输出:视频mp4文件会存放到当前目录中的Output文件夹中
    """


下载链接放上:https://quiryrain.lanzoue.com/iR3zM0notoja  密码:52pj

执行结果.png (42.6 KB, 下载次数: 13)

运行效果图

运行效果图

合成的视频.png (20.09 KB, 下载次数: 3)

下载结果

下载结果

免费评分

参与人数 3吾爱币 +8 热心值 +3 收起 理由
likebbs + 1 谢谢@Thanks!
禁之零零 + 1 + 1 谢谢@Thanks!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
 楼主| QuiryRain 发表于 2023-1-13 18:47 |楼主
aa2923821a 发表于 2023-1-12 08:43
小破站缓存导出不行吗,我之前导歌mv就这么干

有些缓存不了,不过用音轨文件加视频轨文件,可以合成视频,方法通用
推荐
臀臀怪 发表于 2023-1-12 20:32
aa2923821a 发表于 2023-1-12 08:43
小破站缓存导出不行吗,我之前导歌mv就这么干

小伙子你还年轻,有些是没办法缓存的
4#
aa2923821a 发表于 2023-1-12 08:43
小破站缓存导出不行吗,我之前导歌mv就这么干
5#
shamoul 发表于 2023-1-12 16:56
很有用,学到了
6#
hxywbrlzl 发表于 2023-1-12 17:24
又是一个新的下载思路,收藏学习了。之前用的都是现成的软件
7#
whoami233 发表于 2023-1-13 22:25
我一般用you-get
pip install you-get
8#
windgod489 发表于 2023-1-19 07:53
小破站知道被冠名不知咋想
9#
yyn233 发表于 2023-1-25 23:01
画质默认是多少
10#
Nuyoah0824 发表于 2023-1-28 14:20
看起来不错,可以试试
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-25 23:56

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表