一闲话

这一片博客其实和fme没有太大关系,事情是这样的,51放假,我回家后终于有时间,可以追一下《月光骑士》这部美剧。由于很多原因,美剧基本上只能在某些小网站上追。但是这些小网站,有一个很大的问题,就是资源太慢了,动不动卡半天。

后来突发奇想发,我能不能直接写爬虫获取到资源?

由于小网站类型很多,各种资源链接下载方式各不相同,因此,我偷了一个懒,制作了m3u8格式的下载和数据合并的方法。并将其封装到FME里面。

之所以选择FME,是因为我懒得写GUI界面,每次找到新的资源,再去改代码的话非常麻烦,因此直接用FME封装。而且如果我要批量下载网站上的作品,在前期提取视频地址的时候,还能发挥FME的优势,这是最方便的了。

整个部分核心为下载m3u8格式数据,然后对其进行合并,我分别将其封装成了两个自定义转器。

二m3u8格式下载

再次之前先讲一下m3u8格式,一般大家获取到的m3u8网址,下载下来是一个文本文件。如下图所示。

#EXINF下面的则为对应的下载链接,它将整个视频分割成无数个几秒钟的片段,这样不必每次就把整个视频全部下载到浏览器上,极大的减少了服务器的压力。关于m3u8的格式,我就不做过多的讲解,主要说爬取思路。

基本上下载的思路就是,下载index.m3u8文件,然后解析对应的每一个ts文件的地址,最后下载,记住必须要按照现有顺序对其进行整理排序。要不然后续视频拼接的时候就乱了。

下载的实现思路主要还是用的python,具体代码如下:

import requests
from requests.adapters import HTTPAdapter
import os
from threading import Thread
from queue import Queue
import reclass DownloadVideo():def __init__(self, fanout_dir, name, base_url, max_thread):self.headers = {"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Mobile Safari/537.36",}self.video_path = fanout_dir + '\\' + nameself.base_url = base_urlself.session = requests.session()# 去除警告信息requests.packages.urllib3.disable_warnings()self.session.mount('http://', HTTPAdapter(max_retries=3))self.qurl = Queue()self.data = list()self.thread_num = max_threadpass# 发送请求def parse_url(self, url):try:response = self.session.get(url, headers=self.headers, timeout=30, verify=False)return response.contentexcept requests.exceptions.RequestException as e:print(e)passdef get_m3u8_data(self, m3u8_url, base_url):try:print(m3u8_url)data = self.parse_url(m3u8_url)data = data.decode(encoding="utf-8", errors="strict")# print(data)except Exception as e:print(e)return# 不加?贪婪模式,替换所有匹配到的字符串m3u8_data = re.sub('#E.*', '', data).split()m3u8_data_list = []for i in m3u8_data:ts_url = base_url + im3u8_data_list.append(ts_url)return m3u8_data_listdef write_files(self, title, url):print('3.开始下载:' + str(title) + '---' + str(url))r = self.parse_url(url)out_dir = self.video_pathif not os.path.exists(out_dir):os.makedirs(out_dir)file_name = title + '.ts'out_path = os.path.join(out_dir, file_name)# with open(out_path, 'ab') as f: 用这个方法可以将视频以二进制形式追加并写入with open(out_path, 'wb') as f:f.write(r)print('3.下载完成:' + str(title) + '---' + str(url))passdef get_info(self):while not self.qurl.empty():item = self.qurl.get()url = item["url"]title = item["title"]try:self.write_files(title, url)except Exception as e:print(e)def run(self, m3u8_url):# 下载urlurl_list = self.get_m3u8_data(m3u8_url, self.base_url)# print(url_list)for i in range(len(url_list)):item = {}item["title"] = str(i).rjust(5, '0')item["url"] = url_list[i]self.qurl.put(item)# 开始提取下载ths = []for _ in range(self.thread_num):th = Thread(target=self.get_info)th.start()ths.append(th)for th in ths:th.join()

我将其整个封装到了FME里面,转换前参数如下:

  • max_threa为下载的最大线程数,意味着我同时可以进行多少个数据的下载。
  • 基础链接地址表示的,在某些情况下,m3u8文件下的的地址是一个相对的,你需要告诉程序,我要给他拼接上什么样的地址,记得最后是带斜杠”/“的。如果没有则不填写
  • m3u8地址:
  • 保存路径和名称,则是将这一片数据存储的地方,ts文件名称必须要改,因为后续拼接视频的时候是根据文件名称给视频命名的。

三ts文件拼接

下载后的ts文件,是每个几秒钟的视频片段,我们最终肯定是要对其进行合并的。具体代码如下:

class MergeTs():def __init__(self, ffmpeg_path, input_dir, output_dir, max_thread, key_text, key_iv):self.log = fmeobjects.FMELogFile()self.ffmpeg_path = ffmpeg_path######################配置信息##########################self.ts_dir = input_dirself.out_dir = output_dirself.qurl = Queue()self.data = list()self.thread_num = max_thread# 新增解密方式self.keyText = key_textself.keyiv = key_ivdef check_exits(self, path):if not os.path.exists(path):os.makedirs(path)# 将文件合并成一个def merge_ts(self, out_dir, in_dir, files, key_text, key_iv):# 输出路径+文件名称output_fp = open(out_dir, "wb+")for file in files:# print('开始合并' + in_dir + "/" + file)input_file_path = in_dir + "/" + fileinput_fp = open(input_file_path, "rb")file_data = input_fp.read()cryptor = self.decrypt(key_text, key_iv)try:if cryptor is None:output_fp.write(file_data)else:output_fp.write(cryptor.decrypt(file_data))except Exception as exception:input_fp.close()output_fp.close()self.log.logMessageString(exception)return Falseinput_fp.close()output_fp.close()return True# 视频解密def decrypt(self, keyText, keyiv):# 判断是否进行了加密if keyText is None or keyText == '':return None# 判断是否有偏移量if keyiv is not None and keyiv != '':cryptor = AES.new(bytes(keyText, encoding='utf8'), AES.MODE_CBC, bytes(keyiv, encoding='utf8'))else:cryptor = AES.new(bytes(keyText, encoding='utf8'), AES.MODE_CBC, bytes(keyText, encoding='utf8'))return cryptordef ffmpeg2mp4(self, input_file_path):ouput_file_path = input_file_path.split('.flv')[0] + '.mp4'if not os.path.exists(input_file_path):self.log.logMessageString(input_file_path + " 路径不存在!")return Falsecmd = r'{0} -i "{1}" -vcodec copy -acodec copy "{2}"'.format(self.ffmpeg_path, input_file_path, ouput_file_path)self.log.logMessageString('开始执行{0}'.format(cmd))if os.system(cmd) == 0:self.log.logMessageString(input_file_path + "转换成功!")return Trueelse:self.log.logMessageString(input_file_path + "转换失败!")return False# 开始合并def merge_start(self):while not self.qurl.empty():item = self.qurl.get()root = item["root"]files = item["files"]# 检查路径是否有,没有则创建self.check_exits(self.out_dir)out_dir = self.out_dir + "\\" + root.split('\\')[-1] + '.flv'# print(out_dir)self.merge_ts(out_dir, root, files)self.ffmpeg2mp4(out_dir)passdef main(self):# 1.遍历文件,获取数据路径for root, dirs, files in os.walk(self.ts_dir):# 当前目录# print(root.split('\\')[-1])# files.sort()item = {}item["root"] = rootitem["files"] = filesif len(files) > 0:self.qurl.put(item)# print(item)# 多进程开启,合并数据ths = []for _ in range(self.thread_num):th = Thread(target=self.merge_start)th.start()ths.append(th)for th in ths:th.join()

上面的代码需要注意一点,因为是在FME内部的PythonCaller里面执行的,因此我使用的fmeobjects.FMELogFile().logMessageString()方法替代print方法进行日志的输出,这在fme之外使用代码是无法执行的,如果又在外部程序使用的需求,记得改掉即可。

对于上面的功能,我也将其封装到了FME里面,具体参数看下图:

其中使用了ffmpeg.exe这个程序进行视频的转码,因此,大家记得要选择这个程序才能进行拼接。

需要注意的一点是,有些网站的视频是对其进行了加密处理的。我一开始的时候是下了解密的方法,但是其中使用了Crypto这个库,这个库在FME里面没有,所以对加密视频的处理这个功能,我暂未进行启用,有解密需求的,可以下载安装这个第三方库之后,将图下的转换器重新替换一下即可。

对于视频加密解密这部分功能,要讲清楚要很多时间了,我代码里已经有写了解密过程,在此略过不讲。【主要是懒,或许下次?】

最后展示一下下载速度,45分钟的视频,开了16个线程,下载只需要53秒多一点,速度还是很可观的。以后再也不用担心追剧卡顿了。

文末是最喜爱的分享环节,包括FME的工作空间文件和ffmpeg.exe程序

链接:https://pan.baidu.com/s/1cApoUOWFPebbSRFIvIC-7Q
提取码:kxou

如果有喜欢的,可以关注我个人公众号,不务正业的GISER,后续会继续分享一些不务正业的有趣的东西

使用FME封装一个多线程爬取m3u8在线视频的小玩意相关推荐

  1. python爬取m3u8格式视频

    python爬取m3u8格式视频 m3u8原理 脚本环境 爬取步骤 步骤的具体实现 python细节处理说明 参考代码 m3u8原理 当我们在网页播放视频时,网页向服务器发起一个以.m3u8结尾的连接 ...

  2. python多线程爬取m3u8视频(包含AES解密)

    python爬取m3u8视频(包含AES解密) 前情提要 部分代码摘录于某位大哥(写代码的时候收藏书签了的打算写博客的时候带上链接的,无奈手贱删除了chrome用户,所有的书签也没了,找到再补上),在 ...

  3. Python爬取m3u8格式视频并解密ts文件合并转为mp4格式

    一. m3u8是什么格式 m3u8是苹果公司推出的视频播放标准,是m3u的一种,只是编码格式采用的是UTF-8. m3u8准确来说是一种索引文件,使用m3u8文件实际上是通过它来解析对应的放在服务器上 ...

  4. Java多线程爬取豆瓣排行榜Top250(maven)

    总体设计 分析网页 确定需要用到的jar包,并通过pom.xml进行配置 创建一个电影实体类(Film),写入要爬取电影的相关属性,并用set和get方法封装 编写一个多线程爬取Top250的电影程序 ...

  5. 爬取B站视频 - m4s与flv文件的那些事

    参考链接 使用 Python 爬取 B 站视频 爬取B站视频 目录 1. 前言说明 2. 自动化分析 3. 爬取单个视频 4. 批量爬取视频 5. 总结 一.前言说明 ↶ 前言 每次查找资料和研究总是 ...

  6. python多线程爬取ts文件并合成mp4视频

    python多线程爬取ts文件并合成mp4视频 声明:仅供技术交流,请勿用于非法用途,如有其它非法用途造成损失,和本博客无关 目录 python多线程爬取ts文件并合成mp4视频 前言 一.分析页面 ...

  7. 利用协程爬取m3u8视频

    利用协程爬取m3u8视频 ​ 在进行了爬虫的相关学习之后,自己尝试爬取了一些视频,但动辄ts文件就几百个,单线程伤不起那时间,一个一个等实在太慢了,想利用多线程,查看相关资料,又说python是假的多 ...

  8. python多线程爬取多个网址_【Python爬虫】多线程爬取斗图网站(皮皮虾,我们上车)...

    原标题:[Python爬虫]多线程爬取斗图网站(皮皮虾,我们上车) 斗图我不怕 没有斗图库的程序猿是无助,每次在群里斗图都以惨败而告终,为了能让自己在斗图界立于不败之地,特意去网上爬取了斗图包.在这里 ...

  9. Python爬虫系列(三)多线程爬取斗图网站(皮皮虾,我们上车)

    斗图我不怕 最近看了Python多线程的相关内容,并且前几天观看了腾讯课堂潭州学院上面的关于斗图网爬取的公开课,课程内容大致是利用Python多线程爬取斗图(多页),并将图片保存到本地.自己写这篇文章 ...

最新文章

  1. Spring事务配置探究
  2. 嵌入式Linux的特点
  3. Msxml2.XMLHTTP Microsoft.XMLHTTP new XMLHttpRequest
  4. python教程哪个版本好-tensorflow用python哪个版本更好?
  5. hdu 4983(欧拉函数)
  6. CVE-2018-1111漏洞复现-环境搭建与dhcp命令注入
  7. netty源码解解析(4.0)-2 Chanel的接口设计
  8. vue2.0桌面端框架_这款优秀的Vue+ElementUI桌面端一站式框架,爱了!
  9. 造车新势力回港:蔚来能重拾“老大哥”头衔吗?
  10. 压力传感器的制作材料
  11. 高等数学(Calculus I)
  12. 容器技术在云中如何定位
  13. 作为零基础的新手,如何自学Java和JavaEE开发技术?
  14. 英语单词记忆 词源法-思维导图(18)词源st/sist/stat/stin/stem-277
  15. 鸿蒙王者荣耀想要转区吗,王者荣耀开放转区 转区转角色服务要求条件汇总
  16. 银川清华计算机技术培训,银川有没有本地IT技能培训?
  17. intellij idea 2016破解方法
  18. Python PyQt5简介
  19. 关于mikefile 萌新用法
  20. 康拓电梯卡数据分析软件 门禁卡数据分析软件

热门文章

  1. 用户在电商网站中购买成功了,那么它在微服务中经历了什么(转)
  2. 天融信防火墙保存配置_天融信防火墙 通用配置
  3. SAR ADC系列11:分段式CDAC
  4. python Linux学习之 ansible-- ansible test -m ping运行错误
  5. 上海交通大学计算机学院导师介绍,上海交通大学计算机科学与工程系导师教师师资介绍简介-张同珍副教授...
  6. oracle对应字符集汇总,Oracle字符集子集与超级的对应关系
  7. 如何购买企业SSL数字证书?
  8. 开源有魔力 - DolphinScheduler 的 Apache 之路
  9. 我的电脑中的搜索功能用不了怎么办?
  10. 懂得安慰自己,过洒脱的人生