当前位置:   article > 正文

利用Python做一个小姐姐词云跳舞视频

with threadpoolexecutor(max_workers=4) as executor:

作者:北山啦 

https://blog.csdn.net/qq_45176548/article/details/113410073


本文将以哔哩哔哩–乘风破浪视频为例,you-get下载视频,同时利用python爬取B站视频弹幕,并利用opencv对视频进行分割,百度AI进行人像分割,moviepy生成词云跳舞视频,并添加音频。

1. 导入模块

1.1 下载所需模块

我们需要下载很多的模块,所以我们可以使用os.system()方法来自动安装所需模块,当然也有可能下载失败,特别是opencv-python,多安装几次就好啦.

  1. import os
  2. import time
  3. libs = {"lxml","requests","pandas","numpy","you-get","opencv-python","pandas","fake_useragent","matplotlib","moviepy"}
  4. try:
  5. for lib in libs:
  6. os.system(f"pip3 install -i https://pypi.doubanio.com/simple/ {lib}")
  7. print(lib+"下载成功")
  8. except:
  9.     print("下载失败")

1.2 导入模块

在这里统一先导入所需的模块

  1. import os
  2. import re
  3. import cv2
  4. import jieba
  5. import requests
  6. import moviepy
  7. import pandas as pd
  8. import numpy as np
  9. from PIL import Image
  10. from lxml import etree
  11. from wordcloud import WordCloud
  12. import matplotlib.pyplot as plt
  13. from fake_useragent import UserAgent

2. 视频处理

2.1 下载视频

从B站视频下载舞蹈视频:

https://blog.csdn.net/qq_45176548/article/details/113379829

使用you-get方法获取B站视频

2.2 视频分割

使用opencv,将视频的分隔为图片,本文截取 800 张图片来做词云。

opencv中通过VideoCaptrue类对视频进行读取操作以及调用摄像头

2.2.1代码展示

  1. # -*- coding:utf-8 -*-
  2. # @Author : 北山啦
  3. # @Time : 2021/1/29 14:08
  4. # @File : 视频分割.py
  5. # @Software : PyCharm
  6. import cv2
  7. cap = cv2.VideoCapture(r"无价之姐~让我乘风破浪~~~.flv")
  8. while 1:
  9. # 逐帧读取视频 按顺序保存到本地文件夹
  10. ret,frame = cap.read()
  11. if ret:
  12. cv2.imwrite(f".\pictures\img_{num}.jpg",frame)
  13. else:
  14. break
  15. cap.release()   # 释放资源

2.2.2 结果展示

2.3 人像分割

2.3.1创建应用

利用百度AI,创建一个人像分割的应用

2.3.2 Python SDK参考文档

利用参考文档(https://cloud.baidu.com/doc/BODY/s/Rk3cpyo93?_=5011917520845),来进行人像分割

2.3.3 代码展示

  1. # -*- coding:utf-8 -*-
  2. # @Author : 北山啦
  3. # @Time : 2021/1/29 14:38
  4. # @File : 人像分割.py
  5. # @Software : PyCharm
  6. """原文链接:"""
  7. import cv2
  8. import base64
  9. import numpy as np
  10. import os
  11. from aip import AipBodyAnalysis
  12. import time
  13. import random
  14. APP_ID = '******'
  15. API_KEY = '*******************'
  16. SECRET_KEY = '********************'
  17. client = AipBodyAnalysis(APP_ID, API_KEY, SECRET_KEY)
  18. # 保存图像分割后的路径
  19. path = './mask_img/'
  20. # os.listdir 列出保存到图片名称
  21. img_files = os.listdir('./pictures')
  22. print(img_files)
  23. for num in range(1, len(img_files) + 1):
  24. # 按顺序构造出图片路径
  25. img = f'./pictures/img_{num}.jpg'
  26. img1 = cv2.imread(img)
  27. height, width, _ = img1.shape
  28. # print(height, width)
  29. # 二进制方式读取图片
  30. with open(img, 'rb') as fp:
  31. img_info = fp.read()
  32. # 设置只返回前景 也就是分割出来的人像
  33. seg_res = client.bodySeg(img_info)
  34. labelmap = base64.b64decode(seg_res['labelmap'])
  35. nparr = np.frombuffer(labelmap, np.uint8)
  36. labelimg = cv2.imdecode(nparr, 1)
  37. labelimg = cv2.resize(labelimg, (width, height), interpolation=cv2.INTER_NEAREST)
  38. new_img = np.where(labelimg == 1, 255, labelimg)
  39. mask_name = path + 'mask_{}.png'.format(num)
  40. # 保存分割出来的人像
  41. cv2.imwrite(mask_name, new_img)
  42.     print(f'======== 第{num}张图像分割完成 ========')

2.3.4 结果展示

3. 弹幕爬取

由于技术原因,我们改为此视频来获取弹幕,视频链接(https://www.bilibili.com/video/BV1jZ4y1K78N/?spm_id_from=333.788.recommend_more_video.0),哈哈哈哈哈。

3.1 网页分析

通过F12,找到pagelist,通过原始url,找到cid

3.2 观察历史弹幕

清楚元素,展开弹幕列表

日期列表,只有2021年的,点击其他日期,出来了history请求,点击查看

3.3爬取弹幕

3.3.1构造时间序列

该视频发布于2020-08-09,本文爬取该视频2020-08-08到2020-09-08日的历史弹幕数据,构造出时间序列:

  1. import pandas as pd
  2. a = pd.date_range("2020-08-08","2020-09-08")
  3. print(a)
  4. DatetimeIndex(['2020-08-08', '2020-08-09', '2020-08-10', '2020-08-11',
  5. '2020-08-12', '2020-08-13', '2020-08-14', '2020-08-15',
  6. '2020-08-50', '2020-08-17', '2020-08-18', '2020-08-19',
  7. '2020-08-20', '2020-08-21', '2020-08-22', '2020-08-23',
  8. '2020-08-24', '2020-08-25', '2020-08-26', '2020-08-27',
  9. '2020-08-28', '2020-08-29', '2020-08-30', '2020-08-31',
  10. '2020-09-01', '2020-09-02', '2020-09-03', '2020-09-04',
  11. '2020-09-05', '2020-09-06', '2020-09-07', '2020-09-08'],
  12.               dtype='datetime64[ns]', freq='D')

3.3.2 爬取数据

  1. # -*- coding:utf-8 -*-
  2. # @Author : 北山啦
  3. # @Time : 2021/1/29 19:33
  4. # @File : 弹幕爬取.py
  5. # @Software : PyCharm
  6. import requests
  7. import pandas as pd
  8. import re
  9. import csv
  10. from fake_useragent import UserAgent
  11. from concurrent.futures import ThreadPoolExecutor
  12. import datetime
  13. ua = UserAgent()
  14. start_time = datetime.datetime.now()
  15. def Grab_barrage(date):
  16. headers = {
  17. "origin": "https://www.bilibili.com",
  18. "referer": "https://www.bilibili.com/video/BV1jZ4y1K78N?from=search&seid=1084505810439035065",
  19. "cookie": "",
  20. "user-agent": ua.random(),
  21. }
  22. params = {
  23. 'type': 1,
  24. 'oid' : "222413092",
  25. 'date': date
  26. }
  27. r= requests.get(url, params=params, headers=headers)
  28. r.encoding = 'utf-8'
  29. comment = re.findall('<d p=".*?">(.*?)</d>', r.text)
  30. for i in comments:
  31. df.append(i)
  32. a = pd.DataFrame(df)
  33. a.to_excel("danmu.xlsx")
  34. def main():
  35. with ThreadPoolExecutor(max_workers=4) as executor:
  36. executor.map(Grab_barrage, date_list)
  37. """计算所需时间"""
  38. delta = (datetime.datetime.now() - start_time).total_seconds()
  39. print(f'用时:{delta}s')
  40. if __name__ == '__main__':
  41. # 目标url
  42. url = "https://api.bilibili.com/x/v2/dm/history"
  43. start,end = '20200808','20200908'
  44. date_list = [x for x in pd.date_range(start, end).strftime('%Y-%m-%d')]
  45. count = 0
  46.     main()

3.3.3结果展示

4.生成词云图

4.1 评论内容机械压缩去重

对于一条评论来说,有些人可能手误,或者凑字数,会出现将某个字或者词语,重复说多次,因此在进行分词之前,需要做“机械压缩去重”操作。

  1. def func(s):
  2. for i in range(1,int(len(s)/2)+1):
  3. for j in range(len(s)):
  4. if s[j:j+i] == s[j+i:j+2*i]:
  5. k = j + i
  6. while s[k:k+i] == s[k+i:k+2*i] and k<len(s):
  7. k = k + i
  8. s = s[:j] + s[k:]
  9. return s
  10. data["短评"] = data["短评"].apply(func)

4.2 添加停用词和自定义词组

  1. import pandas as pd
  2. from wordcloud import WordCloud
  3. import jieba
  4. from tkinter import _flatten
  5. import matplotlib.pyplot as plt
  6. jieba.load_userdict("./词云图//add.txt")
  7. with open('./词云图//stoplist.txt', 'r', encoding='utf-8') as f:
  8.     stopWords = f.read()

4.3生成词云图

  1. # -*- coding:utf-8 -*-
  2. # @Author : 北山啦
  3. # @Time : 2021/1/29 19:10
  4. # @File : 跳舞词云图生成.py
  5. # @Software : PyCharm
  6. from wordcloud import WordCloud
  7. import collections
  8. import jieba
  9. import re
  10. from PIL import Image
  11. import matplotlib.pyplot as plt
  12. import numpy as np
  13. with open('barrages.txt') as f:
  14. data = f.read()
  15. jieba.load_userdict("./词云图//add.txt")
  16. # 读取数据
  17. with open('barrages.txt') as f:
  18. data = f.read()
  19. jieba.load_userdict("./词云图//add.txt")
  20. # 文本预处理 去除一些无用的字符 只提取出中文出来
  21. new_data = re.findall('[\u4e00-\u9fa5]+', data, re.S)
  22. new_data = "/".join(new_data)
  23. # 文本分词
  24. seg_list_exact = jieba.cut(new_data, cut_all=True)
  25. result_list = []
  26. with open('./词云图/stoplist.txt', encoding='utf-8') as f:
  27. con = f.read().split('\n')
  28. stop_words = set()
  29. for i in con:
  30. stop_words.add(i)
  31. for word in seg_list_exact:
  32. # 设置停用词并去除单个词
  33. if word not in stop_words and len(word) > 1:
  34. result_list.append(word)
  35. # 筛选后统计词频
  36. word_counts = collections.Counter(result_list)
  37. path = './wordcloud/'
  38. img_files = os.listdir('./mask_img')
  39. print(img_files)
  40. for num in range(1, len(img_files) + 1):
  41. img = fr'.\mask_img\mask_{num}.png'
  42. # 获取蒙版图片
  43. mask_ = 255 - np.array(Image.open(img))
  44. # 绘制词云
  45. plt.figure(figsize=(8, 5), dpi=200)
  46. my_cloud = WordCloud(
  47. background_color='black', # 设置背景颜色 默认是black
  48. mask=mask_, # 自定义蒙版
  49. mode='RGBA',
  50. max_words=500,
  51. font_path='simhei.ttf', # 设置字体 显示中文
  52. ).generate_from_frequencies(word_counts)
  53. # 显示生成的词云图片
  54. plt.imshow(my_cloud)
  55. # 显示设置词云图中无坐标轴
  56. plt.axis('off')
  57. word_cloud_name = path + 'wordcloud_{}.png'.format(num)
  58. my_cloud.to_file(word_cloud_name) # 保存词云图片
  59.     print(f'======== 第{num}张词云图生成 ========')

5. 合成视频

如官方文档所介绍的,moviepy是一个用于视频编辑Python库,可以切割、拼接、标题插入,视频合成(即非线性编辑),进行视频处理和自定义效果的设计。总的来说,可以很方便自由地处理视频、图片等文件。

5.1图片合成

  1. # -*- coding:utf-8 -*-
  2. # @Author : 北山啦
  3. # @Time : 2021/1/29 19:10
  4. # @File : 跳舞词云图生成.py
  5. # @Software : PyCharm
  6. import cv2
  7. import os
  8. # 输出视频的保存路径
  9. video_dir = 'result.mp4'
  10. # 帧率
  11. fps = 30
  12. # 图片尺寸
  13. img_size = (1920, 1080)
  14. fourcc = cv2.VideoWriter_fourcc('M', 'P', '4', 'V') # opencv3.0 mp4会有警告但可以播放
  15. videoWriter = cv2.VideoWriter(video_dir, fourcc, fps, img_size)
  16. img_files = os.listdir('.//wordcloud')
  17. for i in range(88, 888):
  18. img_path = './/wordcloud//wordcloud_{}.png'.format(i)
  19. frame = cv2.imread(img_path)
  20. frame = cv2.resize(frame, img_size) # 生成视频 图片尺寸和设定尺寸相同
  21. videoWriter.write(frame) # 写进视频里
  22. print(f'======== 按照视频顺序第{i}张图片合进视频 ========')
  23. videoWriter.release()   # 释放资源

结果展示:

5.2 音频添加

  1. # -*- coding:utf-8 -*-
  2. # @Author : 北山啦
  3. # @Time : 2021/1/29 19:10
  4. # @File : 跳舞词云图生成.py
  5. # @Software : PyCharm
  6. import moviepy.editor as mpy
  7. # 读取词云视频
  8. my_clip = mpy.VideoFileClip('result.mp4')
  9. # 截取背景音乐
  10. audio_background = mpy.AudioFileClip('song.mp3').subclip(0,25)
  11. audio_background.write_audiofile('song1.mp3')
  12. # 视频中插入音频
  13. final_clip = my_clip.set_audio(audio_background)
  14. # 保存为最终的视频 动听的音乐!漂亮小姐姐词云跳舞视频!
  15. final_clip.write_videofile('final_video.mp4')

6. 结果展示

到这里就结束了,如果对你有帮助,欢迎点赞,你的点赞对我很重要。

< END >

微信扫码关注,了解更多内容

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/74893
推荐阅读
相关标签
  

闽ICP备14008679号