示例:私聊获取示例链接
第一步找到 视频资源接口
这是m3u8的资源 获取接口

使用 postman 模拟发送 请求

发现无法获取到数据 报错 403
查看请求头发现 还有其他请求参数
设置请求头

在pyhton 中 使用request 请求

获取到资源文档 发现 链接内容都是 ts文件 采用多线程下载 ts文件
# 采用线程池下载m3u8里的ts
def down_ts():
# 读取 文件内容
with open("./hhls.m3u8", "r", encoding="utf-8") as f:
# n = 0
# 创建 10 个线程
with ThreadPoolExecutor(10) as t:
# 循环 文件内容
for n, line in enumerate(f):
line = line.strip()
# print(line)
# 判断是否是忽略内容
if line.startswith("#"):
# 是则跳过循环
continue
# 提交线程
t.submit(ts_video, n, line)
下载方法
# 下载ts视频 ./hhls 为下载ts视频存放的路径
def ts_video(n, line):
headers = {
'origin' : 'https://xxxxx',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
}
resp3 = requests.get(headers=headers, url=line)
print(resp3.status_code)
with open(f"./hhls/{n}.ts", "wb+") as f:
f.write(resp3.content)
视频下载完成之后 则需要将 ts 文件 合并成MP4 文件
这时则需要使用到 ffmpeg
下载成功后解压即可

执行 合并视频代码
def movie_video():
filePath = "./hhls"
# 获取当前文件夹下 使用文件名称
file_list = os.listdir(filePath)
print(file_list)
li = []
for file in file_list:
# 字符串截取
file = file.split(".")[0]
# 添加进 列表
li.append(int(file))
# 列表进行排序
li.sort()
ts_file_name = []
# 循环列表
for i in li:
i = str(i) + ".ts"
# 添加 文件名进入列表
ts_file_name.append(i)
# 创建或打开文件 执行写入
with open("./hhls/file_list.txt", "w+") as f:
# 循环 文件名列表
for file in ts_file_name:
# 循环写入文件
f.write("file '{}'\n".format(file))
print("file_list.txt已生成")
txt_file = "./hhls/file_list.txt"
mp4 = "./hhls/hhls.mp4"
# 执行合并命令
cmd = f"ffmpeg -f concat -i " + txt_file + " -c copy " + mp4
print(cmd)
try:
# 执行命令
os.system(cmd)
except Exception as e:
print(e)
print("done")
发现报错乱码

乱码解决方法 在 pycharm 中 修改配置 打开 file 下 settings 中 搜索 file encodings 修改字符集为 GBK 即可


这是由于没有将 ffmpeg 添加到环境变量导致
回到桌面 右键点击此电脑 点击属性 添加系统环境变量 ffmpeg.exe 所在的文件位置即可


打开cmd 执行命令 ffmpeg -v 查看是否添加成功

添加成功重启 pycharm 编辑器 即可
重新运行 合并ts文件时报错
Could not find tag for codec bmp in stream #0, codec not currently supported in container
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
Error initializing output stream 0:0 --
这种是利用图床来存储视频切片 文件前被增加了BMP的header信息,导致ffmpeg错误地识别为BMP图片,自然不能合并了。
其实他就是 ts文件,被改成.bmp 后缀,放到图床,达到白嫖图床的目的

那么如何解决这个问题呢
使用16进制查看器WinHex 编辑 删除
47 40 11 之前的数据即可 
片段示例
12.ts 文件 16进制数据

删除 bmp头后 执行合并成功


png 头部信息 ts片段数据

常用文件格式十六进制文件头
JPEG (jpg),文件头:FFD8FF
PNG (png),文件头:89504E47
GIF (gif),文件头:47494638
TIFF (tif),文件头:49492A00
Windows Bitmap (bmp),文件头:424D
CAD (dwg),文件头:41433130
Adobe Photoshop (psd),文件头:38425053
Rich Text Format (rtf),文件头:7B5C727466
XML (xml),文件头:3C3F786D6C
HTML (html),文件头:68746D6C3E
Email [thorough only] (eml),文件头:44656C69766572792D646174653A
Outlook Express (dbx),文件头:CFAD12FEC5FD746F
Outlook (pst),文件头:2142444E
MS Word/Excel (xls.or.doc),文件头:D0CF11E0
MS Access (mdb),文件头:5374616E64617264204A
WordPerfect (wpd),文件头:FF575043
Adobe Acrobat (pdf),文件头:255044462D312E
Quicken (qdf),文件头:AC9EBD8F
Windows Password (pwl),文件头:E3828596
ZIP Archive (zip),文件头:504B0304
RAR Archive (rar),文件头:52617221
Wave (wav),文件头:57415645
AVI (avi),文件头:41564920
Real Audio (ram),文件头:2E7261FD
Real Media (rm),文件头:2E524D46
MPEG (mpg),文件头:000001BA
MPEG (mpg),文件头:000001B3
Quicktime (mov),文件头:6D6F6F76
Windows Media (asf),文件头:3026B2758E66CF11
MIDI (mid),文件头:4D546864
那么问题来了 如何在代码中实现呢
示例:
# bmp标头文件示例
f = open(f'./hhls/648.ts','rb')# 二进制读
# 读取文件流
a = f.read()# 打印读出来的数据
# 转换16进制
hexstr = binascii.b2a_hex(a)
# 转换成 字符串
hexstr = hexstr.decode('UTF-8')
# print(hexstr)
#判断是否 存在 特定标头
header = ['FFD8FF','89504E47','47494638','424D']
for value in header:
# 搜索 判断16进制内容是否 存在 特定标头
if hexstr.startswith(value.lower()) :
# 进行字符串截图
new_hexstr = hexstr[len(value):]
# 字符串转为bytes 类型 数据
new_hexstr = bytes.fromhex(new_hexstr)
f = open(f'./hhls/648.ts', 'wb') # 二进制写模式
f.write(new_hexstr) # 二进制写入
成功合成之后


发现 视频时长不正确 在命令行 执行合并 发现 482.ts文件 有问题无法合并

打开文件发现文件资源有问题 属于无效文件

查看网站后发现 网站资源也丢失这一片段
解决方法 删除 482.ts 文件 重新执行 脚本
或
修改 file_list.txt 删除 file '482.ts' 即可 
重新执行合并命令


合并ts 资源成功
下载方法 优化 后
# 下载ts视频 ./hhls 为下载ts视频存放的路径
def ts_video(n, line):
headers = {
'origin' : 'https://xxxxx',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
}
resp3 = requests.get(headers=headers, url=line)
print(resp3.status_code)
with open(f"./hhls/{n}.ts", "wb+") as f:
f.write(resp3.content)
# bmp标头文件示例
f = open(f'./hhls/{n}.ts','rb')# 二进制读
# 读取文件流
a = f.read()# 打印读出来的数据
# 转换16进制
hexstr = binascii.b2a_hex(a)
# 转换成 字符串
hexstr = hexstr.decode('UTF-8')
# print(hexstr)
#判断是否 存在 特定标头
header = ['FFD8FF','89504E47','47494638','424D']
for value in header:
# 搜索 判断16进制内容是否 存在 特定标头
if hexstr.startswith(value.lower()) :
# 进行字符串截图
new_hexstr = hexstr[len(value):]
# 字符串转为bytes 类型 数据
new_hexstr = bytes.fromhex(new_hexstr)
f = open(f'./hhls/{n}.ts', 'wb') # 二进制写模式
f.write(new_hexstr) # 二进制写入
print(n, "下载完成")
完整代码示例
示例网站地址:私聊获取
import requests
import os
import binascii
from concurrent.futures import ThreadPoolExecutor
def download_video():
headers = {
'origin' : 'xxxxxx',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
}
# 当前链接只有 几分钟 时效 请去示例网站地址 实时获取
link = 'xxxxxx'
resp = requests.get(headers=headers,url=link)
# print(resp)
m3u8text = resp.text
with open("hhls.m3u8", "w") as f:
f.write(m3u8text)
print("hhls.m3u8下载完成")
# 采用线程池下载m3u8里的ts
def down_ts():
# 读取 文件内容
with open("./hhls.m3u8", "r", encoding="utf-8") as f:
# n = 0
# 创建 10 个线程
with ThreadPoolExecutor(10) as t:
# 循环 文件内容
for n, line in enumerate(f):
line = line.strip()
# print(line)
# 判断是否是忽略内容
if line.startswith("#"):
# 是则跳过循环
continue
# 提交线程
t.submit(ts_video, n, line)
# 下载ts视频 ./hhls 为下载ts视频存放的路径
def ts_video(n, line):
headers = {
'origin' : 'xxxxxx',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
}
resp3 = requests.get(headers=headers, url=line)
print(resp3.status_code)
with open(f"./hhls/{n}.ts", "wb+") as f:
f.write(resp3.content)
# bmp标头文件示例
f = open(f'./hhls/{n}.ts','rb')# 二进制读
# 读取文件流
a = f.read()# 打印读出来的数据
# 转换16进制
hexstr = binascii.b2a_hex(a)
# 转换成 字符串
hexstr = hexstr.decode('UTF-8')
# print(hexstr)
#判断是否 存在 特定标头
header = ['FFD8FF','89504E47','47494638','424D']
for value in header:
# 搜索 判断16进制内容是否 存在 特定标头
if hexstr.startswith(value.lower()) :
# 进行字符串截图
new_hexstr = hexstr[len(value):]
# 字符串转为bytes 类型 数据
new_hexstr = bytes.fromhex(new_hexstr)
f = open(f'./hhls/{n}.ts', 'wb') # 二进制写模式
f.write(new_hexstr) # 二进制写入
print(n, "下载完成")
def movie_video():
filePath = "./hhls"
# 获取当前文件夹下 使用文件名称
file_list = os.listdir(filePath)
print(file_list)
li = []
for file in file_list:
# 字符串截取
file = file.split(".")[0]
# 添加进 列表
li.append(int(file))
# 列表进行排序
li.sort()
ts_file_name = []
# 循环列表
for i in li:
i = str(i) + ".ts"
# 添加 文件名进入列表
ts_file_name.append(i)
# 创建或打开文件 执行写入
with open("./hhls/file_list.txt", "w+") as f:
# 循环 文件名列表
for file in ts_file_name:
# 循环写入文件
f.write("file '{}'\n".format(file))
print("file_list.txt已生成")
txt_file = "./hhls/file_list.txt"
mp4 = "./hhls/hhls.mp4"
# 执行合并命令
cmd = f"ffmpeg -f concat -i " + txt_file + " -c copy " + mp4
print(cmd)
try:
# 执行命令
os.system(cmd)
except Exception as e:
print(e)
print("done")
if __name__ == '__main__':
download_video()
down_ts()
movie_video()
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题