└── file.py /file.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import os, shutil 5 | import urllib.request, urllib.error, requests 6 | 7 | 8 | # 打开并读取网页内容 9 | def getUrlData(url): 10 | try: 11 | urlData = urllib.request.urlopen(url, timeout=3) # .read().decode('utf-8', 'ignore') 12 | return urlData 13 | except Exception as err: 14 | print(f'err getUrlData({url})\n', err) 15 | return -1 16 | 17 | 18 | # 下载文件-urllib.request 19 | def getDown_urllib(url, file_path): 20 | try: 21 | urllib.request.urlretrieve(url, filename=file_path) 22 | return True 23 | except urllib.error.URLError as e: 24 | # hasttr(e, 'code'),判断e 是否有.code属性,因为不确定是不是HTTPError错误,URLError包含HTTPError,但是HTTPError以外的错误是不返回错误码(状态码)的 25 | if hasattr(e, 'code'): 26 | print(e.code) # 打印服务器返回的错误码(状态码),如403,404,501之类的 27 | elif hasattr(e, 'reason'): 28 | print(e.reason) # 打印错误原因 29 | 30 | 31 | def getVideo_urllib(url_m3u8, path, videoName): 32 | print('begin run ~~\n') 33 | # urlData = getUrlData(url_m3u8).readlines() 34 | urlData = getUrlData(url_m3u8) 35 | num = 0 36 | tempName_video = os.path.join(path, f'{videoName}.ts') # f'{}' 相当于'{}'.format() 或 '%s'%videoName 37 | # print(urlData) 38 | for line in urlData: 39 | # 解码,由于是直接使用了所抓取的链接内容,所以需要按行解码,如果提前解码则不能使用直接进行for循环,会报错 40 | # 改用上面的readlines()或readline()也可以,但更繁琐些,同样需要按行解码,效率更低 41 | url_ts = line.decode('utf-8') 42 | tempName_ts = os.path.join(path, f'{num}.ts') # f'{}' 相当于'{}'.format() 43 | if not '.ts' in url_ts: 44 | continue 45 | else: 46 | if not url_ts.startswith('http'): # 判断字符串是否以'http'开头,如果不是则说明url链接不完整,需要拼接 47 | # 拼接ts流视频的url 48 | url_ts = url_m3u8.replace(url_m3u8.split('/')[-1], url_ts) 49 | print(url_ts) 50 | getDown_urllib(url_ts, tempName_ts) # 下载视频流 51 | if num == 0: 52 | # 重命名,已存在则自动覆盖 53 | shutil.move(tempName_ts, tempName_video) 54 | num += 1 55 | continue 56 | cmd = f'copy /b {tempName_video}+{tempName_ts} {tempName_video}' 57 | res = os.system(cmd) 58 | if res == 0: 59 | os.system(f'del {tempName_ts}') 60 | # if num == 20: # 限制下载的ts流个数,这个视频挺长有四百多个.ts文件,所以限制一下 61 | # break 62 | num += 1 63 | continue 64 | print(f'Wrong, copy {num}.ts-->{videoName}.ts failure') 65 | return False 66 | os.system(f'del {path}/*.ts') # 调用windows命令行(即cmd)工具,运行命令 67 | filename = os.path.join(path, f'{videoName}.mp4') 68 | shutil.move(tempName_video, filename) 69 | print(f'{videoName}.mp4 finish down!') 70 | 71 | 72 | if __name__ == '__main__': 73 | url_m3u8 = 'http://cntv.hls.cdn.myqcloud.com/asp/hls/2000/0303000a/3/default/e7b1fc31c9af496d85cf647cdffea9db/2000.m3u8' 74 | path = r'G:\videos' 75 | videoName = url_m3u8.split('/')[-2] 76 | getVideo_urllib(url_m3u8, path, videoName) 77 | 78 | 79 | --------------------------------------------------------------------------------