介绍:

在自学爬虫时,一开始就是爬取一些文字(比如小说之类的),再后来变成了图片,再后来变成了视频…
其中最简单的就是对文字的爬取了,从文字过渡到图片也只是多了几行代码而已,但是: 从图片过渡到视频就要 分情况了。


分情况解释:

第一种情况: 链接明确是以 mp4、mkv、rmvb 这类视频格式后缀为结尾的链接,这种下载很简单,和图片下载的方法一样,就是视频文件要比图片大而已。

第二种情况: 另一种,链接是以 m3u8 这类以多个 ts 文件组成的链接。

ts文件 ? 链接: 百度知道。

然而,在进行爬取的过程中,你会发现:第二种情况又有两种呈现方式:

第一种: 网页源码中的链接直接以 m3u8 结尾,这类的链接,推荐使用 FFmpeg 进行下载。(注意该工具下载成功后需要配置环境变量才可以使用。)

使用方法:

import ffmpy3
ffmpy3.FFmpeg(inputs={'http://***.m3u8': None}, outputs={name+'.mp4':None}).run()

FFmpeg 可以帮你下载 m3u8 格式的视频,而且还能帮你自动转换为 mp4 的格式,并且不会出现拼接 ts 文件时乱序的情况。

第二种: 也是我今天着重说的一种情况。网页源码中并没有以 m3u8 格式结尾的链接。而是由在网页中直接请求并解析 ts 文件。

比如以下的视频网站:


分析及爬取:

我们就在当前网站爬取一个前段时间热播的动漫:《天气之子》 来演示用最为基础的 with open() 来爬取 ts 文件并合成为 mp4 格式的方法。
进入 天气之子 的主页,通过控制台我们需要构建一点简单的头文件来防止反爬: (主链接被我修改了,怕被和谐,这里主要分享的是方法。)

header = {'origin': 'https://www.******.tv','referer': 'https://www.******.tv/py/lJWMpVmYqRWb_1.html?158064','user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edg/81.0.416.72'
}

由于我曾经被拉进过网站的黑名单: 所以还是默默的写个代理 IP 吧。

不会写 IP代理 ? 链接: Python爬虫,自建IP地址池.

proxies = ['HTTP://110.243.30.23:9999', 'HTTP://222.189.191.206:9999', 'HTTP://118.212.104.138:9999','HTTP://182.149.83.97:9999', 'HTTP://106.42.163.100:9999', 'HTTP://120.83.107.69:9999','HTTP://60.13.42.135:9999', 'HTTP://60.205.188.24:3128', 'HTTP://113.195.232.23:9999','HTTP://59.62.36.74:9000', 'HTTP://218.2.226.42:80']
proxy = {'HTTP': random.choice(proxies)}  #随机选取一个IP

通过点击每一个 ts 文件,我们发现,对于每一个 ts 文件的请求地址都差不多:具体为:

https://*****/20200508/19312_c9d456ff/1000k/hls/d3276cb180400(****).ts
括号中的 * 代表数字,如: 0001、0002、0003…9999
通过拉动进度条可以快速地查看,最大的数字为 1613。

我们来试着请求 一下某段 ts 文件:

import os
import requests
import randomheader = {'origin': 'https://www.pianku.tv','referer': 'https://www.pianku.tv/py/lJWMpVmYqRWb_1.html?158064','user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edg/81.0.416.72'
}
proxies = ['HTTP://110.243.30.23:9999', 'HTTP://222.189.191.206:9999', 'HTTP://118.212.104.138:9999','HTTP://182.149.83.97:9999', 'HTTP://106.42.163.100:9999', 'HTTP://120.83.107.69:9999','HTTP://60.13.42.135:9999', 'HTTP://60.205.188.24:3128', 'HTTP://113.195.232.23:9999','HTTP://59.62.36.74:9000', 'HTTP://218.2.226.42:80']
proxy = {'HTTP': random.choice(proxies)}
print(proxy)
path = './Spider/'if os.path.exists(path + "天气之子/"):pass
else:os.makedirs(path + "天气之子/")def download():url = 'https://*****/20200508/19312_c9d456ff/1000k/hls/d3276cb1804000001.ts'with open(path + "天气之子/" + str(url).split('/')[-1][-7:], 'wb') as f:#已知最大的数字为 1613 ,所以以最后4位数字作为 ts 文件的名字。try:r = requests.get(url, proxies=proxy, headers=header)r.raise_for_status()r.encoding = 'utf-8'f.write(r.content)except:print('请求失败!')if __name__ == '__main__':download()

于是我们就得到了第一个 ts 文件:

双击查看,结果是:可以打开播放:

接下来我们试着将所有的 ts 文件下载下来,并且以最后4位数字作为 ts 文件的名字:
首先想到的就是用 for 循环,问题倒是没有,就是太慢了,所以改进为使用线程池来下载:

#
#   前面的部分不变,在此省略
#def download(num):# https://*****/20200508/19312_c9d456ff/1000k/hls/d3276cb180400(****).tsurl = 'https://*****/20200508/19312_c9d456ff/1000k/hls/d3276cb180400{:0>4d}.ts'.format(num)#在这里用了 str.format() 中的 {:0>4d} 来控制位数with open(path + "天气之子/" + str(url).split('/')[-1][-7:], 'wb') as f:try:r = requests.get(url, proxies=proxy, headers=header)r.raise_for_status()r.encoding = 'utf-8'f.write(r.content)print('正在下载第 {} 个片段。'.format(num))except:print('请求失败!')if __name__ == '__main__':# 开启线程池start_time = time.time()pool = ThreadPool(100)results = pool.map(download, range(1, 1613+1))  # range含左不含右pool.close()pool.join()

但是: 一波未平一波又起,下载时,有些片段会秒下载,而有些片段则会下载的特别慢,甚至有些片段直接下载失败!!!!!
如果没有某个片段,剧情不就会跳着走吗?这可咋整,刚进入剧情,正为男女主角捏把汗的时候,一下就给我踢出来了,满头黑人问号,气得我直接口吐芬芳。

解决方案: 我们知道,当我们修改最后的四位数字时,它会直接跳转下载对应的片段,难道要一个一个的去看 ts 文件?不、不、不,当然不需要。
接下来,看看我的简单想法: 创建一个 list 将所有失败的尾数全都追加进去,在第一次程序下载结束时,仅对该 list 中对应的 ts 文件进行下载:

#
#   前面的部分不变,在此省略
#def download(num, flag=0): ## https://*****/20200508/19312_c9d456ff/1000k/hls/d3276cb1804001613.tsurl = 'https://*****/20200508/19312_c9d456ff/1000k/hls/d3276cb180400{:0>4d}.ts'.format(num)with open(path + "天气之子/" + str(url).split('/')[-1][-7:], 'wb') as f:try:r = requests.get(url, proxies=proxy, headers=header, timeout=5)#对于下载比较慢的情况,设置 timeout = 5 r.raise_for_status()r.encoding = 'utf-8'print('正在下载第 {} 个片段。'.format(num))f.write(r.content)if flag == 1:   # 对于从 list 中第二次下载的情况,下载成功,则从 list 中删去。failure_list.remove(num)except:print('请求失败!')if num not in failure_list:failure_list.append(num) # 如果下载失败或者超时,则添加进 listdef check_ts():print("开始检查:")while failure_list:  #()、{}、[] 都相当于 falsefor num in failure_list:download(num, 1)# 传入标识 1if __name__ == '__main__':# 开启线程池start_time = time.time()pool = ThreadPool(100)results = pool.map(download, range(1, 1613+1))pool.close()pool.join()check_ts()

结果如下:


ts 文件的合并与转换为 mp4 格式:

经过小小的等待,现在,我们已经下载完成了所有的 ts 文件。
下载完成,有人会说:诶~, ts 文件都是可以播放的,直接用播放器顺序播放不久行了嘛。
但是: 我还没发现有哪款视频播放器能做到完全无卡顿感的切换这么多的视频,每几秒钟就 “ 卡顿 ” 一下,观影效果大打折扣。
所以还是乖乖的把它们都合并了吧。至于怎么合并,且听我慢慢道来:

第一步:我们先定义一个用于合并 ts 文件的函数:def get_video():
第二步:利用 files = os.listdir( path ) 拿到所有的文件名,所有的 ts 文件都是从小到大排列的,所以我们拿到的文件名也是有顺序的。
第三步:遍历每一个文件名, 通过 with open() 以二进制的方式打开并读取该文件(f1),接着再使用一个 with open() 打开目标文件(f2),将从 f1 中读取出来的二进制文件以二进制追加写的方式写入到 f2 中 。

遍历时用 tqdm 库进行显示进度条。结果因为转换的速度太快,根本看不到进度条时怎么走的,几乎是秒转换,所以:我是为了什么加的进度条来着

Python爬虫:用最普通的方法爬取ts文件并合成为mp4格式相关推荐

  1. python爬虫入门_3种方法爬取古诗文网站

    目的: 爬取古诗文网的古诗词,获取详细信息,目标网站:https://www.gushiwen.org/default.aspx?page=1 1.根据网页分析可知 下面包含了当前页面的所有信息,所以 ...

  2. python拼接大量ts文件_Python爬取.ts文件,合并为mp4

    目标:爬影视网站ts文件到本地,合并成mp4文件 下载ts文件 本着不重复造轮子的精神(好吧其实是我懒),想用迅雷批量下载爬取,但是迅雷提供的通配符过于简单无法构造URL,只能自己写脚本 如下: # ...

  3. 从入门到入土:Python爬虫学习|实例练手|爬取百度产品列表|Xpath定位标签爬取|代码注释详解

    此博客仅用于记录个人学习进度,学识浅薄,若有错误观点欢迎评论区指出.欢迎各位前来交流.(部分材料来源网络,若有侵权,立即删除) 本人博客所有文章纯属学习之用,不涉及商业利益.不合适引用,自当删除! 若 ...

  4. Python 爬虫实战,模拟登陆爬取数据

    Python 爬虫实战,模拟登陆爬取数据 从0记录爬取某网站上的资源连接: 模拟登陆 爬取数据 保存到本地 结果演示: 源网站展示: 爬到的本地文件展示: 环境准备: python环境安装 略 安装r ...

  5. Python爬虫笔记(3)- 爬取丁香园留言

    Python爬虫笔记(3)- 爬取丁香园留言 爬取丁香园留言:主要用到了模拟登录 爬取丁香园留言:主要用到了模拟登录 import requests, json, re, random,time fr ...

  6. python爬虫之股票数据定向爬取

    python爬虫之股票数据定向爬取 功能描述 目标:获取上交所和深交所所有股票的名称和交易的信息 输出:保存到文件中 技术路线:requests-bs4-re 前期分析 选取原则:股票的信息静态存在H ...

  7. python爬虫入门练习:BeautifulSoup爬取猫眼电影TOP100排行榜,pandas保存本地excel文件

    传送门:[python爬虫入门练习]正则表达式爬取猫眼电影TOP100排行榜,openpyxl保存本地excel文件 对于上文使用的正则表达式匹配网页内容,的确是有些许麻烦,替换出现任何的差错都会导致 ...

  8. python爬虫 - 起点女生榜单爬取 - 1

    python爬虫 - 起点女生榜单爬取 ​ 最近一直在追庆余年,顺带瞄了一眼小说,真真是精彩(虽然因为范闲多妻的设定接受不了就放弃了). ​ 说来说去,还是钟爱女频的修仙小说,所以就想爬一下起点女生网 ...

  9. Python爬虫实战系列(一)-request爬取网站资源

    Python爬虫实战系列(一)-request爬取网站资源 python爬虫实战系列第一期 文章目录 Python爬虫实战系列(一)-request爬取网站资源 前言 一.request库是什么? 二 ...

最新文章

  1. Linux监听进程是否存在,并加入定时任务
  2. Mysql高性能优化规范建议,太厉害了!
  3. 保存模型后无法训练_模型构建到部署实践
  4. HashMap和ArrayList初始大小和扩容后的大小
  5. 从714里连续减去6减几次得0_数学干货 | 小学数学1—6年级基础知识整理 ,预习复习都能用...
  6. RESTful API实现APP订餐实例
  7. 故障转移集群仲裁盘_MongoDB负载均衡、故障转移及海量数据应对方案
  8. 控制台 钢铁雄心2_钢铁雄心2中共事件代码 | 手游网游页游攻略大全
  9. mysql 数据库设计实例_一个简单数据库设计例子
  10. urlrewrite 规则报错
  11. 202206-2 寻宝大冒险
  12. 为什么计算机专业英语很重要,英语对计算机专业的重要性及如何提高英语水平...
  13. 北京高级项目经理市场需求
  14. “AI四小龙”神话破灭?依图终止IPO,云从大裁员,旷视巨亏不止
  15. word文档中表格顶头怎么调整_word使用技巧之-Word文字处理技巧,学会不求人!...
  16. 单片机---HLK-W801蓝牙遥控点灯
  17. matlab截取5到10秒音频,如何截取音频中的一段
  18. winform 两个区域保持固定距离_【麻辣烫】川渝区域零担十强分析:余氏东风、力展、宇鑫、金泓达快运、长吉、西部风、海风快运、绍平、迪丰、健隆......
  19. 微信云函数的使用步骤
  20. 计算机考研必须去一线城市,考研211院校和一线城市如何选择?

热门文章

  1. 图像加噪与滤波处理(python+opencv)
  2. AUTOSAR MCAL解析:MCU
  3. pr中导出视频的应用,快速制作竖版短视频
  4. python协程多任务爬取虎牙美女主播图片
  5. 华为日历怎么显示一月_华为P20使用感受
  6. 计算机毕业设计Java班费收支管理系统(源码+系统+mysql数据库+lw文档)
  7. webpack 打包报错:Can't resolve '.\dist\bundle.js' in 'E:\vivian....'
  8. DNS解析时发现域名和IP不一致,访问了该域名会如何(大厂真题)
  9. Codeforces 并查集题集(Disjoint Sets Union Step1)
  10. minecraft java版皮肤查看_我的世界官网针对Minecraft Java版玩家皮肤的更新