python爬取B站视频

参考:https://cloud.tencent.com/developer/article/1768680

参考的代码有点问题,请求头需要修改,上代码:

import requests
import re  # 正则表达式
import pprint
import json
from moviepy.editor import AudioFileClip, VideoFileClip
from bs4 import BeautifulSoup as bsheaders = {# 防盗链 告诉服务器 我们请求的url网址是从哪里跳转过来的'referer': 'https://www.bilibili.com/a','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'
}def send_request(url):response = requests.get(url=url, headers=headers)return responsedef get_video_data(html_data):"""解析视频数据"""# 提取视频的标题soup = bs(html_data, 'lxml')title = soup.find_all(name='h1',attrs={"class":"video-title special-text-indent"})[0].get_text()# print(title)# 提取视频对应的json数据json_data = re.findall('<script>window\.__playinfo__=(.*?)</script>', html_data)[0]# print(json_data)  # json_data 字符串json_data = json.loads(json_data)pprint.pprint(json_data)# 提取音频的url地址audio_url = json_data['data']['dash']['audio'][0]['backupUrl'][0]print('解析到的音频地址:', audio_url)# 提取视频画面的url地址video_url = json_data['data']['dash']['video'][0]['backupUrl'][0]print('解析到的视频地址:', video_url)video_data = [title, audio_url, video_url]return video_datadef save_data(file_name, audio_url, video_url):# 请求数据print('正在请求音频数据')audio_data = send_request(audio_url).contentprint('正在请求视频数据')video_data = send_request(video_url).contentwith open(file_name + '.mp3', mode='wb') as f:f.write(audio_data)print('正在保存音频数据')with open(file_name + '.mp4', mode='wb') as f:f.write(video_data)print('正在保存视频数据')def merge_data(video_name):print('视频合成开始:', video_name)audioclip = AudioFileClip(video_name+'.mp3')videoclip = VideoFileClip(video_name+'.mp4')# 3.获取视频和音频的时长video_time = videoclip.durationaudio_time = audioclip.duration# 4.对视频或者音频进行裁剪if video_time > audio_time:# 视频时长>音频时长,对视频进行截取videoclip_new = videoclip.subclip(0, audio_time)audioclip_new = audioclipelse:# 音频时长>视频时长,对音频进行截取videoclip_new = videoclipaudioclip_new = audioclip.subclip(0, video_time)# 5.视频中加入音频video_with_new_audio = videoclip_new.set_audio(audioclip_new)# 6.写入到新的视频文件中video_with_new_audio.write_videofile("output.mp4",codec='libx264',audio_codec='aac',temp_audiofile='temp-video.m4a',remove_temp=True)print('视频合成结束:', video_name)url = 'https://www.bilibili.com/video/BV1bK421a7qG/?spm_id_from=333.1007.tianma.6-4-22.click'
response = send_request(url)
response.encoding = requests.utils.get_encodings_from_content(response.text)[0]
html_data = response.text
video_data = get_video_data(html_data)
save_data(video_data[0], video_data[1], video_data[2])
merge_data(video_data[0])

效果

小姐姐挺靓,就是左下角有水印,想办法去除水印,参考:python实战之去除视频水印&字幕_python 去除视频水印-CSDN博客

import os
import sys
import cv2
import numpy
from moviepy import editorTEMP_VIDEO = 'temp.mp4'class WatermarkRemover():def __init__(self, video_path, output, threshold: int, kernel_size: int):self.threshold = threshold  # 阈值分割所用阈值self.kernel_size = kernel_size  # 膨胀运算核尺寸self.video_path = video_pathself.output = output#根据用户手动选择的ROI(Region of Interest,感兴趣区域)框选水印或字幕位置。def select_roi(self, img: numpy.ndarray, hint: str) -> list:'''框选水印或字幕位置,SPACE或ENTER键退出:param img: 显示图片:return: 框选区域坐标'''COFF = 0.7w, h = int(COFF * img.shape[1]), int(COFF * img.shape[0])resize_img = cv2.resize(img, (w, h))roi = cv2.selectROI(hint, resize_img, False, False)cv2.destroyAllWindows()watermark_roi = [int(roi[0] / COFF), int(roi[1] / COFF), int(roi[2] / COFF), int(roi[3] / COFF)]return watermark_roi#对输入的蒙版进行膨胀运算,扩大蒙版的范围def dilate_mask(self, mask: numpy.ndarray) -> numpy.ndarray:'''对蒙版进行膨胀运算:param mask: 蒙版图片:return: 膨胀处理后蒙版'''kernel = numpy.ones((self.kernel_size, self.kernel_size), numpy.uint8)mask = cv2.dilate(mask, kernel)return mask#根据手动选择的ROI区域,在单帧图像中生成水印或字幕的蒙版。def generate_single_mask(self, img: numpy.ndarray, roi: list, threshold: int) -> numpy.ndarray:'''通过手动选择的ROI区域生成单帧图像的水印蒙版:param img: 单帧图像:param roi: 手动选择区域坐标:param threshold: 二值化阈值:return: 水印蒙版'''# 区域无效,程序退出if len(roi) != 4:print('NULL ROI!')sys.exit()# 复制单帧灰度图像ROI内像素点roi_img = numpy.zeros((img.shape[0], img.shape[1]), numpy.uint8)start_x, end_x = int(roi[1]), int(roi[1] + roi[3])start_y, end_y = int(roi[0]), int(roi[0] + roi[2])gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)roi_img[start_x:end_x, start_y:end_y] = gray[start_x:end_x, start_y:end_y]# 阈值分割_, mask = cv2.threshold(roi_img, threshold, 255, cv2.THRESH_BINARY)return mask#通过截取视频中多帧图像生成多张水印蒙版,并通过逻辑与计算生成最终的水印蒙版def generate_watermark_mask(self, video_path: str) -> numpy.ndarray:'''截取视频中多帧图像生成多张水印蒙版,通过逻辑与计算生成最终水印蒙版:param video_path: 视频文件路径:return: 水印蒙版'''video = cv2.VideoCapture(video_path)success, frame = video.read()roi = self.select_roi(frame, 'select watermark ROI')mask = numpy.ones((frame.shape[0], frame.shape[1]), numpy.uint8)mask.fill(255)step = video.get(cv2.CAP_PROP_FRAME_COUNT) // 5index = 0while success:if index % step == 0:mask = cv2.bitwise_and(mask, self.generate_single_mask(frame, roi, self.threshold))success, frame = video.read()index += 1video.release()return self.dilate_mask(mask)#根据手动选择的ROI区域,在单帧图像中生成字幕的蒙版。def generate_subtitle_mask(self, frame: numpy.ndarray, roi: list) -> numpy.ndarray:'''通过手动选择ROI区域生成单帧图像字幕蒙版:param frame: 单帧图像:param roi: 手动选择区域坐标:return: 字幕蒙版'''mask = self.generate_single_mask(frame, [0, roi[1], frame.shape[1], roi[3]], self.threshold)  # 仅使用ROI横坐标区域return self.dilate_mask(mask)def inpaint_image(self, img: numpy.ndarray, mask: numpy.ndarray) -> numpy.ndarray:'''修复图像:param img: 单帧图像:parma mask: 蒙版:return: 修复后图像'''telea = cv2.inpaint(img, mask, 1, cv2.INPAINT_TELEA)return teleadef merge_audio(self, input_path: str, output_path: str, temp_path: str):'''合并音频与处理后视频:param input_path: 原视频文件路径:param output_path: 封装音视频后文件路径:param temp_path: 无声视频文件路径'''with editor.VideoFileClip(input_path) as video:audio = video.audiowith editor.VideoFileClip(temp_path) as opencv_video:clip = opencv_video.set_audio(audio)clip.to_videofile(output_path)def remove_video_watermark(self):'''去除视频水印'''if not os.path.exists(self.output):os.makedirs(self.output)filenames = [os.path.join(self.video_path, i) for i in os.listdir(self.video_path)]mask = Nonefor i, name in enumerate(filenames):if i == 0:# 生成水印蒙版mask = self.generate_watermark_mask(name)# 创建待写入文件对象video = cv2.VideoCapture(name)fps = video.get(cv2.CAP_PROP_FPS)size = (int(video.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)))video_writer = cv2.VideoWriter(TEMP_VIDEO, cv2.VideoWriter_fourcc(*'mp4v'), fps, size)# 逐帧处理图像success, frame = video.read()while success:frame = self.inpaint_image(frame, mask)video_writer.write(frame)success, frame = video.read()video.release()video_writer.release()# 封装视频(_, filename) = os.path.split(name)output_path = os.path.join(self.output, filename.split('.')[0] + '_no_watermark.mp4')  # 输出文件路径self.merge_audio(name, output_path, TEMP_VIDEO)if os.path.exists(TEMP_VIDEO):os.remove(TEMP_VIDEO)def remove_video_subtitle(self):'''去除视频字幕'''if not os.path.exists(self.output):os.makedirs(self.output)filenames = [os.path.join(self.video_path, i) for i in os.listdir(self.video_path)]roi = []for i, name in enumerate(filenames):# 创建待写入文件对象video = cv2.VideoCapture(name)fps = video.get(cv2.CAP_PROP_FPS)size = (int(video.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)))video_writer = cv2.VideoWriter(TEMP_VIDEO, cv2.VideoWriter_fourcc(*'mp4v'), fps, size)# 逐帧处理图像success, frame = video.read()if i == 0:roi = self.select_roi(frame, 'select subtitle ROI')while success:mask = self.generate_subtitle_mask(frame, roi)frame = self.inpaint_image(frame, mask)video_writer.write(frame)success, frame = video.read()video.release()video_writer.release()# 封装视频(_, filename) = os.path.split(name)output_path = os.path.join(OUTPUT_PATH, filename.split('.')[0] + '_no_sub.mp4')  # 输出文件路径self.merge_audio(name, output_path, TEMP_VIDEO)if os.path.exists(TEMP_VIDEO):os.remove(TEMP_VIDEO)# 去水印
video_path = 'video'
output_path = 'output'
remover = WatermarkRemover(video_path,output_path,threshold=80, kernel_size=5)
remover.remove_video_watermark()   
#去字幕
# remover = WatermarkRemover(video_path,output_path,threshold=80, kernel_size=5)
# remover.remove_video_subtitle()

效果一般吧:

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

wps斜线表头并分别打字教程

wps斜线表头怎么做并分别打字&#xff1a; 1、首先选中我们想要设置的表头。 2、接着右键选中它&#xff0c;点击“设置单元格格式” 3、然后点击上方“边框”选项卡。 4、随后选择图示的斜线&#xff0c;点击“确定” 5、设置完成后&#xff0c;我们只要在其中打字就可以在斜…

【教学类-09-08】20240405细线迷宫图04(正方形)迷宫格子数量测试+左上角加格子数(15CM横版一页-1份横版)

作品展示 背景说明 从8*8开始&#xff0c;可以生成了迷宫图了。 代码测试&#xff1a; 第一次&#xff1a;8-30格 # 15CM正方形手工纸上 以15*15格子为基础&#xff0c;测试0-14,16-30的格子num1 # int(input(几张&#xff08;30份&#xff09;\n))print(-----------1、 生成…

盘点中国优秀付费资源站WordPress主题

中国优秀的付费资源站WordPress主题&#xff0c;它们专注于资源管理和分享&#xff0c;提供了丰富的功能和用户体验&#xff1a; 资源宝&#xff08;ziyuanbao&#xff09;&#xff1a;这是一款功能强大的资源站主题&#xff0c;支持多种资源类型的上传、分类和展示&#xff0…

elment UI el-date-picker 月份组件选定后提交后台页面显示正常,提交后台字段变成时区格式

需求&#xff1a;要实现一个日期的月份选择<el-date-picker :typeformData.dateType :value-formatdateFormat v-modelformData.leaveFactoryDateplaceholder选择月份></el-date-picker>错误示例&#xff1a;将日期显示类型(type)dateType或将日期绑定值的格式(val…

免费图片转excel方案大全

随着信息技术的发展&#xff0c;我们经常会遇到需要将图片中的数据转换成Excel表格的情况。这种需求在数据分析、报表制作、信息整理等领域尤为常见。然而&#xff0c;许多人在面对这一任务时感到困惑&#xff0c;不知道如何进行。本文将为大家介绍几种免费的图片转Excel方案&a…

Linux 内核移植exfat驱动

简介&#xff1a; Linux系统默认可以自动识别到fat32格式的盘&#xff0c;但fat32支持的文件不能大于4G&#xff0c;所以只能将移动硬盘和U盘格式化为NTFS和exFAT这两种格式的&#xff0c;对于U盘最好格式化为exFAT。 Linux5.4以上的内核原生支持exfat格式&#xff0c;不需要你…

ARM FVP平台的terminal窗口大小如何设置

当启动ARM FVP平台时&#xff0c;terminal窗口太小怎么办&#xff1f;看起来非常累眼睛&#xff0c;本博客来解决这个问题。 首先看下ARM FVP平台对Host主机的需求&#xff1a; 通过上图可知&#xff0c;UART默认使用的是xterm。因此&#xff0c;我们需要修改xterm的默认字体设…

dm8 开启归档模式

dm8 开启归档模式 1 命令行 [dmdbatest1 dm8]$ disql sysdba/Dameng123localhost:5237服务器[localhost:5237]:处于普通打开状态 登录使用时间 : 3.198(ms) disql V8 SQL> select name,status$,arch_mode from v$database;行号 NAME STATUS$ ARCH_MODE ----------…

flink on yarn

前言 Apache Flink&#xff0c;作为大数据处理领域的璀璨明星&#xff0c;以其独特的流处理和批处理一体化模型&#xff0c;成为众多企业和开发者的首选。它不仅能够在处理无界数据流时展现出卓越的实时性能&#xff0c;还能在有界数据批处理上达到高效稳定的效果。本文将简要…

磁盘如何分配数据数据

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 磁盘如何分配数据 数据切割&#xff1a; 按照固定长度进行切割---》编码翻译&#xff08;常用&#xff09; 计算机要求按照8bit(字节)进…

MATLAB近红外光谱分析技术应用

郁磊副教授&#xff0c;主要从事MATLAB编程、机器学习与数据挖掘、数据可视化和软件开发、生理系统建模与仿真、生物医学信号处理&#xff0c;具有丰富的实战应用经验&#xff0c;主编《MATLAB智能算法30个案例分析》、《MATLAB神经网络43个案例分析》相关著作。已发表多篇高水…

36.基于SpringBoot + Vue实现的前后端分离-高校汉服租赁网站系统(项目 + 论文)

项目介绍 本站是一个B/S模式系统&#xff0c;采用SpringBoot Vue框架&#xff0c;MYSQL数据库设计开发&#xff0c;充分保证系统的稳定性。系统具有界面清晰、操作简单&#xff0c;功能齐全的特点&#xff0c;使得基于SpringBoot Vue技术的高校汉服租赁网站系统设计与实现管理…

mysql语句学习

SQL Select语句完整的执行顺序&#xff1a; 1、from子句组装来自不同数据源的数据&#xff1b; &#xff08;先join在on&#xff09; 2、where子句基于指定的条件对记录行进行筛选&#xff1b; 3、group by子句将数据划分为多个分组&#xff1b; 4、使用聚集函数进行计算&a…

开源AGV调度系统OpenTCS中的任务分派器(dispatcher)详解

OpenTCS中的任务分派器dispatcher详解 1. 引言2. 任务分派器(dispatcher)2.1 默认的停车位置选择2.2 可选停车位置属性2.3 默认的充电位置选择2.4 即时运输订单分配 3. 默认任务分派器的配置项4. 参考资料与源码 1. 引言 openTCS是一项著名的开源运输控制系统&#xff0c;我在…

第五篇:3.4 用户归因和受众(User attribution and audience) - IAB/MRC及《增强现实广告效果测量指南1.0》

翻译计划 第一篇概述—IAB与MRC及《增强现实广告效果测量指南》之目录、适用范围及术语第二篇广告效果测量定义和其他矩阵之- 3.1 广告印象&#xff08;AD Impression&#xff09;第三篇广告效果测量定义和其他矩阵之- 3.2 可见性 &#xff08;Viewability&#xff09;第四篇广…

SpringBoot+ECharts+Html 字符云/词云案例详解

1. 技术点 SpringBoot、MyBatis、thymeleaf、MySQL、ECharts 等 2. 准备条件 在mysql中创建数据库echartsdb&#xff0c;数据库中创建表t_comment表&#xff0c;表中设置两个字段word与count&#xff0c;添加表中的数据。如&#xff1a;附件中的 echartsdb.sql 3. SpringBoot…

el-table实现表格内部横向拖拽效果

2024.4.2今天我学习了如何对el-table表格组件实现内部横向拖拽的效果&#xff0c;效果&#xff1a; 代码如下&#xff1a; 一、创建utils/底下文件 const crosswise_drag_table function (Vue){// 全局添加table左右拖动效果的指令Vue.directive(tableMove, {bind: function…

智慧开发平台免!费!申请试用

原创 F学社 F学社 2024-04-01 17:13 江苏 扫描二维码即可申请试用 01 智慧开发平台简介 F1 WIFI智慧教育平台是可支持线上线下联动的基于FPGA的口袋式数字系统学习平台。其采用了AMD、Altera、安路、高云等国外国内主流公司的FPGA进行数字系统方向的教学实验设计&#xff0c…

Pyecharts绘制条形图

前言 条形图是一种把连续数据画成数据条的表现形式&#xff0c;通过比较不同组的条形长度&#xff0c;从而对比不同组的数据量大小。描绘条形图的要素有3个&#xff1a;组数、组宽度、祖限。绘制条形图时&#xff0c;不同组之间是由空隙的。条形用来比较两个或两个以上的价值&a…

Golang并发模型-Pipeline模型、Fan-in Fan-out模型

这段时间由于项目的需要&#xff0c;本人正在研究关于如何优雅的进行go的并发&#xff0c;以下是结合资料和视频的结果&#xff0c;文末会给出参考资料 Go语言的并发模型主要通过goroutine和channel实现&#xff0c;通过这个我们可以更有效地使用IO和CPU 这里我们围绕生成一个…