利用协程爬取m3u8视频

​ 在进行了爬虫的相关学习之后,自己尝试爬取了一些视频,但动辄ts文件就几百个,单线程伤不起那时间,一个一个等实在太慢了,想利用多线程,查看相关资料,又说python是假的多线程,而且爬取视频这操作也属于IO阻塞操作多的那种,感觉时间提升也不大,多线程和多进程还有协程,协程挺适合这种的,就毅然决然的使用协程了。注:各位大佬轻喷

一.查看网站并分析

1.找到各集数对应网站

首先理清爬取思路,对我这种刚入门的菜鸡来说,爬视频就是看它是不是mp4,或者是不是m3u8格式的,但如标题所言,我今天找的这个是m3u8格式的。直接查看网站源码,如图所示,我们想爬取所有集数首先需要找到这些集数的href

可以看到,我们如果想进这些集数的网站里面得到m3u8文件还是需要进行拼接操作的,这样才能得到进一步m3u8文件。

​ 我们首先进入第一集里面看一看,瞅一瞅,熟悉的打开网站,熟悉的搜索video,打开一看,哇,

是不是很简单

我的上帝啊,瞧瞧那document上面一排是什么,哇,是iframe标签,看来还需要打开一个网站,这标签代表着视频是在内嵌的框架播放的,因为网页中嵌入的<Iframe></Iframe>所包含的内容与整个页面是一个整体(上面这句专业的话那肯定不是我说的),大概就是相当于另一个网站吧。直接requests肯定得不到m3u8文件了。接下来找到那个内嵌网站

2.找到内嵌网站

接下里我们就直接进入网站源码里面进行查找吧,腚眼一看

这不就找到了内嵌网站了吗,只是斜杠在处理的时候需要换一下,这里注意,处理的时候需要转义一下,单斜杠替换的时候不会处理掉的。

3.进入内嵌网站拿到m3u8

进入视频网站,可以知道,整个屏幕都是视频,我们怎么查看源码呢,同样是按F12,在sources里面打开网址路径对应的文件夹下打开,可以找到m3u8文件

什么,你说你看到上面也有一个m3u8文件

我才不会跟你说我写这一篇博客的时候才看到,没事,大不了多一个步骤。刷新页面,可以看到这个m3u8的预览

很明显,我们需要通过这个m3u8文件拿到完整的m3u8文件,

当拿到完整的m3u8文件之后,我们也可以通过这个网站先看一下完整的m3u8文件预览

对味了,啊,那居然还有加密,可以看到是AES-128加密,没事,我们到时候把每一集的m3u8文件这个对应URI拿到并且得到key就行,从uri里面得到密码直接解密,AES的原理详情我也不是很清楚,但好像解密步骤就那回事,需要看看是AES的什么类型。这些可以拿到每一集的m3u8文件了,并且边解密边写入文件

4.将ts文件写入对应的文件夹

这里就利用到我们需要的协程了,直接贴完整代码吧,首先是总体思路

总体思路就是这样,其他的都是一些细枝末节了,接下来也就是看协程怎么运用了。至于ts的合并,就放在下边,也不多赘述了,主要就是利用顺序来合并,自动合并的话顺序有些问题。

import os
import globfor t in range(0,14):if t < 10:x = glob.glob0(f"./第0{t}集/*.ts")print(len(x))with open(f"第0{t}集总合并.ts", "ab") as g:for i in range(0, len(x) - 1):with open(f"./第0{t}集/{i}.ts", 'rb') as xx:g.write(xx.read())else:x = glob.glob(f"./第{t}集/*.ts")print(len(x))with open(f"第{t}集总合并.ts", "ab") as g:for i in range(0, len(x) - 1):with open(f"./第{t}集/{i}.ts", 'rb') as xx:g.write(xx.read())

二.完整代码

import os
import random
import aiofiles
from lxml import html
import requests
import asyncio
import aiohttp
import re
import datetime
from Crypto.Cipher import AES
import timeetree = html.etree
episode_list = []
html_list = []
headers = {'User-Agent': 'Mozilla / 5.0(WindowsNT10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / ''91.0.4472.124Safari / 537.36 '}def get_key(name):with open(f"{name}的m3u8.txt", "r") as f:for i in f:# 使用正则来得到密码连接x = re.compile(r'URI="(.*?)"')t = x.findall(i)if len(t):# print(t[0])# 直接把密码原文得到,byte类型resp = requests.get(t[0], headers=headers).content# print(resp)return resp# 正式写入文件夹里面的ts文件
# 必须得用n来排序,要不然顺序乱了
async def download_ts_descrpt(name, line, n, key,sem):
#这里就是调用同时并发协程的数量async with sem:# aiohttp.ClientSession() as session:可以放在上一个函数打开文件上面,因为我的操作相当于每一次运用协程# 都创建一个连接池,不建议我这样的做法async with aiohttp.ClientSession() as session:async with session.get(url=line, headers=headers) as f:#需要利用aiofiles来打开文件,也是异步操作async with aiofiles.open(f"{name}/{n}.ts", 'wb') as x:t = await f.content.read()                      #使用协会时候需要使用read()# 利用密钥进行解密操作,CBC为猜的,偏移量数量设置跟解出来的密码个数相同aes = AES.new(key=key, IV=b'0000000000000000', mode=AES.MODE_CBC)await x.write(aes.decrypt(t))# 创建保存ts的文件夹,从m真实的m3u8文件里面读取ts
async def create_ts_encrpt(name, key):count = 0#使用count来计数,这样不会使协程写入的时候,ts文件顺序变乱tasks = []#判断是否有文件夹 ,如果有就跳过,没有就创建if not os.path.exists(f'{name}'):os.makedirs(f"{name}")#这里注意,协程里面再次创建协程,这就是进行异步操作,把每一步ts文件添加到协程任务列表#sem = asyncio.Semaphore(5)代表允许的并发协程数量为5,这里不建议设多,也不建议删掉,太多# 的话容易信号灯超时,也就是aiohttp.ClientSession创建的连接池里面请求,网站会响应不过来sem = asyncio.Semaphore(5)async with aiofiles.open(f"./{name}的m3u8.txt", mode='r') as f:async for line1 in f:if line1.startswith("#"):continueelse:line1 = line1.strip()# print(line1)# 添加另外一个协程事件进行操作,这就是写入加密得tstasks.append(download_ts_descrpt(name, line1,  count, key,sem))count += 1await asyncio.wait(tasks)# 把第二层m3u8文件写下来
async def download_m3u82(url, name):async with aiohttp.ClientSession() as session:async with session.get(url, headers=headers) as f:f1 = await f.content.read()# 因为只能写入content所以不需要decodewith open(f"{name}的m3u8.txt", 'wb') as f2:f2.write(f1)# 这里得到每一个密钥然后传入下一个协程函数。这里调用了get_key函数得到每一个密钥key_encrpt = get_key(name)await create_ts_encrpt(name, key_encrpt)# 把第一层m3u8文件写下来,并把第二层m3u8的文件读出来
async def download_m3u8(url, name):async with aiohttp.ClientSession() as session:async with session.get(url, headers=headers) as f:f1 = await f.content.read()# 因为只能写入content所以不需要decodewith open(f"{name}.txt", 'wb') as f2:f2.write(f1)#这里就是读出来with open(f"{name}.txt", 'r', encoding='utf-8') as y:for line in y:if line.startswith("#"):continueelse:# 去掉空白和换行符line = line.strip()line = "https://vod2.buycar5.cn" + line# print(line)await download_m3u82(line, name)  #又传入下一个函数# 在视频里面把每一个m3u8文件拿出来
async def get_html_m3u8(url, name):async with aiohttp.ClientSession() as session:async with session.get(url, headers=headers) as f:html2 = await f.content.read()html2 = html2.decode('utf-8')# print(html2)html2_m3u8 = re.findall(r'var main = "(.*?)";', html2)[0]html2_m3u8 = 'https://vod2.buycar5.cn' + html2_m3u8await download_m3u8(html2_m3u8, name)# 从每一集的链接里面把视频的链接提取出来
async def get_html_m3u8_pre(url, name):async with aiohttp.ClientSession() as session:          #实例化session通过session来getasync with session.get(url, headers=headers) as f:html1 = await f.content.read()html1 = html1.decode('utf-8')# print(html1),第一集吗,格式跟其他集数有所不同可以理解if name == "第01集":html1_m3u8 = re.findall(r'"link_pre":"","url":"(.*?)","url_next"', html1)[0].replace("\\", "")      #这里就是双斜杠,文中提到的需要转义的地方else:html1_m3u8 = re.findall(r'.html","url":"(.*?)","url_next"', html1)[0].replace("\\", "")# print(html1_m3u8)await get_html_m3u8(html1_m3u8, name)           #使用await调用协程函数#得到每一集的初始链接
async def get_html(url):tasks = []  #因为有12集,从主页面的li下面的得到的每一集的链接需要进行拼接,并且将12集用协程来完成,创建协程列表resp = requests.get(url, headers=headers).content.decode('utf-8')resp = etree.HTML(resp)resp_list = resp.xpath('//ul[@class="stui-content__playlist clearfix"]')for res in resp_list:episode = res.xpath('./li/a/@href')                         #得到名字和网址,此时返回的都是列表,注意episode_name = res.xpath('./li/a/text()')# print(episode_name)for i in range(0, len(episode)):episode[i] = "https://www.autonicdq.com" + episode[i]tasks.append(get_html_m3u8_pre(episode[i], episode_name[i]))  #逐项添加协程任务,此时协程任务的函数写在这里面await asyncio.wait(tasks)                                           #执行协程函数# 得到主页面的的每一集的链接if __name__ == '__main__':t1 = datetime.datetime.now()   #记录开始时间url_main = "https://www.autonicdq.com/voddetail/4002.html"loop = asyncio.get_event_loop()         #协程的开始实例化一个loop对象loop.run_until_complete(get_html(url_main))     #在loop对象添加要完成的任务t2 = datetime.datetime.now()    #记录结束时间的print(t2 - t1)

速度比正常快了很多,虽然把协程并发数量进行了限制,但不限制,网站遭不住
注:该文章仅供学习交流

利用协程爬取m3u8视频相关推荐

  1. Python爬虫——aiohttp异步协程爬取同程旅行酒店评论

    大家好!我是霖hero Python并发编程有三种方式:多线程(Threading).多进程(Process).协程(Coroutine),使用并发编程会大大提高程序的效率,今天我们将学习如何选择多线 ...

  2. 送书 | aiohttp异步协程爬取同程旅行酒店评论并作词云图

    大家好!我是啃书君! Python并发编程有三种方式:多线程(Threading).多进程(Process).协程(Coroutine),使用并发编程会大大提高程序的效率,今天我们将学习如何选择多线程 ...

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

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

  4. Python分别用单线程,多线程,异步协程爬取一部小说,最快仅需要5s

    文章目录 单线程爬取 多线程爬取 异步协程爬取 本文运用了三种方式爬取一整部小说,分别运用了单线程爬取,多线程爬取和异步协程爬取. 小说网址:` http://www.doupo321.com/dou ...

  5. python从网址爬图片协程_Python爬虫多任务协程爬取虎牙MM图片

    查看: 4420|回复: 241 [作品展示] Python爬虫多任务协程爬取虎牙MM图片 电梯直达 发表于 2019-4-17 21:35:47 | 只看该作者 |倒序浏览 |阅读模式 马上注册,结 ...

  6. 链家网开源java_异步协程爬取链家租房信息

    异步协程抓取链家数据+pandas写入csv import asyncio import aiohttp import pandas from bs4 import BeautifulSoup fro ...

  7. Python初级爬虫(利用多任务协程爬取虎牙MM图片)

    Python多任务协程下载虎牙直播MM图片 # coding = utf-8 import re import gevent from gevent import monkey, pool impor ...

  8. 协程爬取整站豆瓣网络

    爬取豆瓣网络思路: 从标签页进入,提取所有标签URL 进入每个标签页,提取所有列表URL 进入每个列表页,提取每一页的详情URL和下一页列表URL 进入每个详情页,拿到书名 如此往复循环,直到数据抓取 ...

  9. 多协程爬取中大微博内容(以及转发数,点赞数,评论数)

    这个是在之前的微博爬取(Python)–中大微博前100条微博内容以及评论转发点赞数目爬取 的并发版本 代码 import requests from gevent import monkey imp ...

最新文章

  1. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 按钮:禁用按钮
  2. 12.PHP_PDO数据库抽象层
  3. hibernate 继承映射
  4. C C++ 面试知识总结,包含STL,数据结构等
  5. linux分区知识,Linux硬盘分区知识
  6. 自定义Dictionary支持线程安全
  7. Ubuntu switch window switch terminal tab
  8. matlab计算截断误差,Matlab相位截断误差仿真综述.doc
  9. www.how2j.com_HOW-TO:快速开始使用Spring 4.0,以构建简单的REST-Like API(演练)
  10. matlab出错及解决办法,Linux下使用Matlab符号函数出错的解决办法
  11. 网友的VOIP总结 1
  12. ValidateRequest=false 不在.net2.0 中该怎么办?
  13. 如何实现扫码登陆 扫码登陆原理
  14. 多御安全浏览器升级1.7.6版,新增扫描二维码功能
  15. dede后台登陆提示 验证码不正确 解决办法
  16. 杀毒软件 McAfee 创始人自杀,75 年传奇人生画下句号
  17. html文本如何逐渐淡入,CSS如何实现文字淡入效果
  18. 以P2P网贷为例互联网金融产品如何利用大数据做风控?
  19. 常见的拖垮中小公司技术团队的10宗罪
  20. 市场调研报告-全球与中国4K手术显示器市场现状及未来发展趋势

热门文章

  1. 推荐一款注册表清理软件(含注册码)
  2. 利用简单游戏项目教你如何用java如何画对象
  3. 黑马程序员VUE学习笔记-小黑记事本案例
  4. 读书笔记:跃迁,成为高手的技术
  5. Flowable实战-Camel使用
  6. mac 查看本机 ip
  7. vivado技巧总结
  8. cherrytree安装出现see the logfile for detaile错误的处理
  9. 风投大亨蒂尔对神秘大数据公司Palantir估值折价40%
  10. 眼动追踪:用户体验设计利器_眼动追踪:如何观察点击之间的差距(以及原因)