Python自动获取字母站视频

news2024/11/29 19:54:05

如果有疑问的话可以在我的谈论群:706128290 来找我

目录

前言

二、编写代码

1.引入库

2.编写主类

3. 自动获取cookies值和生成headers

4.获取命令行参数

运行效果


前言

browser_cookie3 第三方模块

browser_cookie3是browser_cookie模块的分支,它可以获取到电脑上的浏览器cookies,本次程序会使用到此模块。


一、HTML玄机

        在小破站的任意一个视频html中,head标签下都有一个script。里面有window.__playinfo__json数据

 

通过JSON在线解析及格式化验证 - JSON.cn 进行解析,我看到了以下内容

 

 天助我也!我想要的视频链接不就是在这里吗?

二、编写代码

1.引入库

代码如下:

# 处理windows.__playinfo__中的json
import json 

# 后面使用命令行获取链接
import sys
import os
import getopt

# 用于请求和解析链接
import requests
from fileid.fileid import Newid # 生成随机文件名
from tqdm import tqdm
from bs4 import BeautifulSoup

# 自定义的功能文件
import getHeaders
import bvid_aid

2.编写主类

代码如下:

PATH: str = os.path.split(__file__)[0]
COOKIE: bool = False
OUTPUTPATH: str = PATH
PAGE: list = [
    None
]

class GBV:
    def __init__(self, _url: str, _browser: int, _params) -> None:
        self.url = _url
        self.params = _params
        self.headers = getHeaders.get(_browser)
        self.title = None
        self.audio = None
        self.video = None
        self.tqdm = tqdm(range(100))
        self.tqdm.set_description(f"Url is: {self.url}")
    
    def move(self, file: str, toPath: str) -> str:
        if os.path.isfile(file):
            rfp = open(file, "rb")
        else:
            return None

        if os.path.isfile(toPath) == False:
            if os.path.isdir(toPath):
                toPath = os.path.join(toPath, self.title+".mp4")
            else:
                return None
        try:
            with open(toPath, "wb") as wfp:
                wfp.write(rfp.read())
        except OSError:
            toPath = os.path.join(OUTPUTPATH, Newid(10).newfileid()+".mp4")
            with open(toPath, "wb") as wfp:
                wfp.write(rfp.read())

        rfp.close()
        os.remove(file)
        return toPath

    def GetPlayinfoData(self) -> tuple:
        with requests.get(self.url, headers=self.headers, params=self.params) as get:
            self.title = BeautifulSoup(get.text, "lxml").find_all("h1")[0].attrs['title']
            data = BeautifulSoup(get.text, "lxml").find_all("script")[2].text.split("__playinfo__=")[-1]
            data = json.loads(data)
            
            self.audio = data['data']['dash']['audio'][0]['baseUrl']
            self.video = data['data']['dash']['video'][0]['baseUrl']

        return (self.title, self.audio, self.video)


    def save(self) -> None:
        randomStr = os.path.join(os.getcwd(), Newid(5).newfileid()+".mp4")
        outputJoin = os.path.join(os.getcwd(), "output.mp4")
        tempMp4Join = os.path.join(os.getcwd(), "temp.mp4")
        tempMp3Join = os.path.join(os.getcwd(), "temp.mp3")
        ffempgJoin = os.path.join(PATH, "ffmpeg.exe")

        with requests.get(self.audio, headers=self.headers) as AudioGet:
            with open(tempMp3Join, "wb") as faudio:
                self.tqdm.set_description("保存音频文件....")
                faudio.write(AudioGet.content)
                faudio.close()
        
        self.tqdm.update(50)

        with requests.get(self.video, headers=self.headers) as VideoGet:
            with open(tempMp4Join, "wb") as fvideo:
                self.tqdm.set_description("保存视频文件...")
                fvideo.write(VideoGet.content)
                fvideo.close()
        os.popen(
            fr"{ffempgJoin} -y -i {tempMp4Join} {outputJoin}"
        ).read()

        os.popen(
            fr"{ffempgJoin} -y -i {outputJoin} -i {tempMp3Join} -c:v copy -c:a copy -bsf:a aac_adtstoasc {randomStr}",
            ).read()

        moveRturn = self.move(f"{randomStr}", OUTPUTPATH)

        self.tqdm.update(50)
        self.tqdm.close()
        if COOKIE:
            with open(f"{PATH}/.cookie", "w+", encoding="utf-8") as wfp:
                wfp.write(COOKIE)
        
        print("\n删除缓存...")
        os.remove(tempMp4Join)
        os.remove(tempMp3Join)
        os.remove(outputJoin)
        
        print(f"\nOk!视频保存文件为:{moveRturn}")
    

    def run(self, bvid: str) -> None:
        global OUTPUTPATH
        url = "https://api.bilibili.com/x/web-interface/wbi/view/detail"
        params = {
            "bvid": bvid,
            "aid": bvid_aid.getAID(bvid),
        }
        videos = {}
        with requests.get(url, params=params, headers=self.headers) as get:
            page_all = 1
            for i in get.json()['data']['View']['pages']:
                videos[i['page']] = i['part']
                page_all += 1

            if OUTPUTPATH == os.path.split(__file__)[0]:
                try:
                    OUTPUTPATH = os.path.join(
                        os.getcwd(),
                        get.json()['data']['View']['title']
                    )
                    if os.path.isdir(OUTPUTPATH) == False:
                        os.mkdir(OUTPUTPATH)
                except OSError as oserror:
                    print(f"{oserror}\n程序将随机生成文件夹名。")
                    OUTPUTPATH = os.path.join(
                        os.getcwd(),
                        Newid(10).newfileid()
                    )
                    if os.path.isdir(OUTPUTPATH) == False:
                        os.mkdir(OUTPUTPATH)

            if PAGE[0] == "ALL":
                for key, value in videos.items():
                    self.params = {
                        "p": i
                    }
                    self.GetPlayinfoData()
                    self.title = value
                    self.save()
            elif (type(PAGE) == list) and (PAGE[0] != None):
                for i in PAGE:
                    if i <= int(page_all):
                        self.params = {
                            "p": i
                        }
                        self.GetPlayinfoData()
                        self.title = f"{i}."+videos[i]
                        self.save()
            elif PAGE[0] == None:
                self.GetPlayinfoData()
                self.save()

1.run函数用于读取用户输入的数据并处理,再启动相应函数

2.GetPlayinfoData就是用于处理window__playinfo__对象中的数据的

2.save函数用于下载音频与视频,再使用ffmpeg合并后保存文件。


3. 自动获取cookies值和生成headers

GetBilibiliCookies.py

import browser_cookie3

class GetBrowser_cookies:
    def __init__(self, browser: int = 0) -> None:
        self.Bkeys = [
            "buvid4",
            "b_nut",
            "b_lsid",
            "buvid3",
            "i-wanna-go-back",
            "_uuid",
            "FEED_LIVE_VERSION",
            "home_feed_column",
            "browser_resolution",
            "buvid_fp",
            "header_theme_version",
            "PVID",
            "SESSDATA",
            "bili_jct",
            "DedeUserID",
            "DedeUserID__ckMd5",
            "b_ut",
            "CURRENT_FNVAL",
            "sid",
            "rpdid"
        ]

        try:
            if browser == 0:
                self.browserCookes = browser_cookie3.edge()
            if browser == 1:
                self.browserCookes = browser_cookie3.chrome()
            if browser == 2:
                self.browserCookes = browser_cookie3.firefox()
        except browser_cookie3.BrowserCookieError:
            self.browserCookes = None
        
        except PermissionError as PE:
            self.browserCookes = None
            raise PermissionError(f"{PE}\n可能是浏览器引起的问题,可以尝试重装浏览器")


    def get(self) -> str:
        cookies = ""
        for i in self.browserCookes:
            if i.name in self.Bkeys:
                cookies += f"{i.name}={i.value}; "

        return cookies
    
    def getValue(self, key: str) -> str:
        for i in self.browserCookes:
            if key == i.name:
                return i.value
        return ""

为什么要获取cookies值?当然没有cookie值也行,但是下载下来的文件一般都是低画质的。但是你登录了账户在浏览器,就可以通过浏览器记录的cookies来提交服务器。 前提是你在浏览器登录了bilibili账户。

getHeaders.py

此处为生成headers的程序

import GetBilibiliCookies

USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
REFERER = "https://www.bilibili.com/"

def get(browser: int = 0) -> dict:
    return {
        "User-Agent":USER_AGENT,
        "cookie": GetBilibiliCookies.GetBrowser_cookies(browser).get(),
        "Referer": REFERER
    }

 bvid_aid.py

import requests

import getHeaders

def getAID(bvid: str) -> int:
    aid = None
    url = f'https://api.bilibili.com/x/web-interface/view?bvid={bvid}'
    with requests.get(url, headers=getHeaders.get()) as get:
        if get.status_code == 200:
            aid = get.json()['data']['aid']
    
    return aid

4.获取命令行参数

代码如下:

def main(_url: str, _browser: int, bvid: str, params: dict) -> None:
    gbv = GBV(_url, _browser, params)
    gbv.run(bvid)


def help() -> None:
    print("""
    ########################################################################
    #   Get Bilibili Video (gbv)
    #   Author: PYmili
    #   Email: mc2005wj@163.com
    ########################################################################

        Command:
            --cookie or -c [Url Cookies]
            --input_url or -i [Video URL]
            --browser or -b [edge(default), chrome, firefox]
            --output or -o [Output file or path]
            --page or -p [start-end / all] Select an array of videos to download
    """)

if __name__ == '__main__':
    URL = None
    BROWSER = 0
    BVID = None
    PARAMS = {}

    options, argv = getopt.getopt(
        sys.argv[1:], "i:c:b:o:p:",
        ["--input_url=", "--cookie=", "--browser=", "--output=", "--page="]
    )

    for key, value in options:
        if key in ["-i", "--input_url"]:
            splitValue = value.split("video")[-1]
            splitValue = splitValue.split("/", 1)[-1].split("/", 1)
            URL = value
            BVID = splitValue[0]
            if splitValue[-1]:
                for i in splitValue[-1][1:].split("&"):
                    try:
                        PARAMS[i.split("=")[0]] = eval(i.split('=')[-1])
                    except SyntaxError:
                        PARAMS[i.split("=")[0]] = str(i.split('=')[-1])
        if key in ["-c", "--copkie"]:
            COOKIE = value
        if key in ["-b", "--browser"]:
            if value == "chrome":
                BROWSER = 1
            elif value == "firefox":
                BROWSER = 2
        if key in ["-o", "--output"]:
            if os.path.isdir(value):
                OUTPUTPATH = value
            else:
                print(f"没有:{value} 这个路径。")
        if key in ["-p", "--page"]:
            if "-" in value:
                start, end = value.split("-")
                PAGE = [i for i in range(int(start), int(end)+1)]
            elif value in ["all", "ALL", "All"]:
                PAGE[0] = "ALL"
            else:
                PAGE.append(int(value))




    if (URL != None) and (BVID != None):
        main(URL, BROWSER, BVID, PARAMS)
    else:
        help()

这就是获取终端输入的传输来运行程序 。


运行效果

当没有输入参数时:

基础输入格式:

完整参数:

--cookie 或者 -c [此处填写cookies]

--input_url 或者 -i [填入B站视频链接]
--browser 或者 -b [edge(default), chrome, firefox 有这三个浏览器供选择默认edge]
--output 或者 -o [文件输出路径,默认当前位置] 

--page 或者 -p [start-end / all] 选择要下载的视频阵列如:0-100或者 all 全部下载


以上就是本篇内容,如果有疑问的话可以在我的谈论群:706128290 来找我,下次再见拜拜!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/768892.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Asymmetric Gained Deep Image Compression With Continuous Rate Adaptation文献复现

前言 相关论文阅读自行解决,这里主要是记录代码的学习与实验的复现 github地址 此代码非官方部署代码,而是私人实现的。 本博客仅做学习记录。 1 代码学习 1.1 主要框架部分 这里的主编解码器与高斯建模的方式,采用的是同joint上下联合自回归一样的方式,主要的改动在增益…

【Linux】使用云服务器搭建Linux环境

目录 1.Linux是什么 2.Linux的环境搭建 3.使用Xshell登录主机 1.Linux是什么 Linux&#xff0c;全称GNU/Linux&#xff0c;是一套免费使用和自由传播的类Unix操作系统&#xff0c;是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统。 简单来说&#xff0c;Lin…

图文详解Java参数传递类型

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Linux用户和用户组

Linux是多用户、多任务操作系统 一般来说&#xff0c;一个服务分配一个用户&#xff0c;这个用户只拥有这个服务相关文件的相关权限&#xff0c;如果用户不需要登陆&#xff0c;连密码都可以不分配&#xff0c;一般来说&#xff0c;非法分子都是获取当前进程的的权限来攻击服务…

自然语言处理: 第五章Attention注意力机制

自然语言处理: 第五章Attention注意力机制 理论基础 Attention&#xff08;来自2017年google发表的[1706.03762] Attention Is All You Need (arxiv.org) &#xff09;&#xff0c;顾名思义是注意力机制&#xff0c;字面意思就是你所关注的东西&#xff0c;比如我们看到一个非…

vue3中echarts的使用

效果&#xff1a; 代码&#xff1a; <div class"outcharbox"><a-row :gutter"10"><a-col :span"8" v-for" (item, index) in linesobjdata" :key"item.MonitorItemId"><monitoringItemsChart :colorI…

49天精通Java,第40天,jd-gui反编译class文件,解决jd-gui中文乱码问题

目录 专栏导读一、添加局部变量二、反编译class文件三、解决乱码问题四、产品经理就业实战1、内容简介2、作者简介 专栏导读 本专栏收录于《49天精通Java从入门到就业》&#xff0c;本专栏专门针对零基础和需要进阶提升的同学所准备的一套完整教学&#xff0c;从0开始&#xf…

【SQL应知应会】表分区(四)• MySQL版

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习&#xff0c;有基础也有进阶&#xff0c;有MySQL也有Oracle 分区表 • MySQL版 前言一、分区表1.非分区表2.分区…

系统学习Linux-SSH远程服务(二)

概念 安全外壳协议&#xff0c;提供安全可靠的远程连接 特点 ssh是工作在传输层和应用层的协议 ssh提供了一组管理命令 ssh 远程登陆 scp 远程拷贝 sftp 远程上传下载 ssh-copy-id ssh keygen 生成 提供了多种身份验证机制 身份验证机制 密码验证 需要提供密码 密…

vue element select下拉框回显展示数字

vue element select下拉框回显展示数字 问题截图&#xff1a; 下拉框显示数字可以从数据类型来分析错误&#xff0c;接收的数据类型是字符串&#xff0c;但是value是数字类型 <el-form-item prop"classifyLabelId" :label"$t(item.classifyLabelId)"…

051、事务设计之TiDB事务实现方式

事务在TiDB中的存储 分布式事务 提交的第一阶段&#xff0c;会用三个CF 来存放这些数据信息&#xff0c; 一类列簇对应一类键值对&#xff0c; 第一个CF(default)存放的是数据 的键值对。第二个存放的是锁信息。 第三个对应的是提交信息。 put<3_100,Frank> 3_100: prim…

LeetCode·每日一题·1851. 包含每个查询的最小区间·优先队列(小顶堆)

题目 示例 思路 离线查询&#xff1a; 输入的结果数组queries[]是无序的。如果我们按照输入的queries[]本身的顺序逐个查看&#xff0c;时间复杂度会比较高。 于是&#xff0c;我们将queries[]数组按照数值大小&#xff0c;由小到大逐个查询&#xff0c;这种方法称之为离线查询…

Go语言之接口(interface)

1.1 、多态的含义 在java里&#xff0c;多态是同一个行为具有不同表现形式或形态的能力&#xff0c;即对象多种表现形式的体现&#xff0c;就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定&#xff0c;而是在程序运行期间才确定&am…

T5模型: Transfer Text-to-Text Transformer(谷歌)

&#x1f525; T5由谷歌发表于2019&#xff0c;《Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer》&#xff0c;最终版本发布在&#xff1a;JMLR。 一句话总结T5: 大一统模型&#xff0c;seq2seq形式完成各类nlp任务&#xff0c;大数据集…

Docker 的前世今生:从社区到市场,从领域到技术应用的全方位分析

博主 默语带您 Go to New World. ✍ 个人主页—— 默语 的博客&#x1f466;&#x1f3fb; 《java 面试题大全》 &#x1f369;惟余辈才疏学浅&#xff0c;临摹之作或有不妥之处&#xff0c;还请读者海涵指正。☕&#x1f36d; 《MYSQL从入门到精通》数据库是开发者必会基础之…

下载编译Chromium

参考&#xff1a;Mac上本地编译Chrome浏览器踩坑笔记&#xff08;2021.02最新&#xff09; - 掘金 For Mac: 一、下载编译工具链&#xff1a;deptool git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git export PATH"$PATH:/Users/yumlu/co…

jib进行本地打包,并上传本地镜像仓库

使用 Jib 进行本地打包和上传到本地镜像仓库是一种方便的方式&#xff0c;而无需编写 Dockerfile。Jib 是一个开源的 Java 容器镜像构建工具&#xff0c;它可以直接将 Java 项目打包为镜像&#xff0c;并将其推送到容器镜像仓库。 gradle 进行jib的配置 import java.time.Zon…

第53步 深度学习图像识别:Bottleneck Transformer建模(Pytorch)

基于WIN10的64位系统演示 一、写在前面 &#xff08;1&#xff09;Bottleneck Transformer "Bottleneck Transformer"&#xff08;简称 "BotNet"&#xff09;是一种深度学习模型&#xff0c;在2021年由Google的研究人员在论文"Bottleneck Transfor…

MaxCompute与 Mysql 之单字段转多行

在实际数据处理中&#xff0c;可能会遇到行列转换的数据处理&#xff0c;在 MaxCompute 与 AnalyticDB MySQL 数据处理与转换 介绍过如多行转一行&#xff0c;本篇主要介绍将逗号分割的字段转成多行。 一、MaxCompute 实现方式 在MaxCompute中有TRANS_ARRAY函数&#xff0c;可…

显示一行或两行多出的文字用省略号代替

以上就是一行的效果&#xff0c;超出宽度就用...代替 .recommendContainer .scrollItem text{/* 单行文本溢出隐藏 省略号代替 */display: block;white-space: nowrap; /*溢出不换行*/overflow: hidden; /*溢出隐藏*/text-overflow: ellipsis; /*溢出的内容已...代替*/} 多…