• 售前

  • 售后

热门帖子
入门百科

Python爬虫爬取ts碎片视频+验证码登录功能

[复制链接]
尹恩沛 显示全部楼层 发表于 2021-10-25 20:07:03 |阅读模式 打印 上一主题 下一主题
目次


  • 一、实现登录账号

    • 1.获取验证码地点                                                                              

  • 二、实现ts碎片视频下载,并转换为mp4格式

    • 1.分析视频下载地点
    • 2.批量下载ts视频片断

  • 三、总结
目标:爬取本身账号中购买的课程视频。

一、实现登录账号

这里接纳的是手动输入验证码的方式,有本领的盆友也可以通过图像辨认的方式自动填写验证码。登录后,接纳session保持登录。

1.获取验证码地点                                                                              

第一步:起首查看验证码对应的代码,可以从图中看到验证码图片的地点是:https://per.enetedu.com/Common/CreateImage?tmep_seq=1613623257608
颜色标红的部分tmep_seq=1613623257608,是为了解决欣赏器缓存题目加的时间戳,因此真正的验证码图片地点是:https://per.enetedu.com/Common/CreateImage

第二步:找出登录时提交的表单内容和POST地点。
(1) 不填写用户名密码和验证码,直接点击登录,使用Chrome欣赏器的Network查抄,找到POST地点:https://per.enetedu.com/AdminIndex/LoginDo

(2) 继承向下看,找到提交的表单 Form Data。

因此带有验证码的登录代码如下:
  1. import requests
  2. from PIL import Image
  3. #用户名-密码-验证码方式,登录
  4. CaptchaUrl = "https://per.enetedu.com/Common/CreateImage" #获取验证码地址
  5. PostUrl = "https://per.enetedu.com/AdminIndex/LoginDo"  #post登录信息地址
  6. client = requests.Session()
  7. username = '替换为自己的用户名'
  8. password = '替换为自己的密码'
  9. qr_code = client.get(CaptchaUrl)
  10. open('login.jpg', 'wb').write(qr_code.content) #将验证码图片保存至本地
  11. img = Image.open('login.jpg')
  12. img.show()  #打开图片
  13. code = input("请输入验证码: \n") #输入验证码
  14. postData = {      #构造POST表单
  15. 'email': username,
  16. 'pwd': password,
  17. 'validateCode': code,
  18. 'x': '22',
  19. 'y': '19'
  20. }
  21. result = client.post(PostUrl,postData) #向PostUrl提交表单
复制代码
二、实现ts碎片视频下载,并转换为mp4格式


1.分析视频下载地点

登录成功后,查抄视频播放div对应的代码,计划找到视频地点直接生存至当地。结果,如下图所示,整个视频是被分割成一段一段的.ts文件,分段加载到页面中播放。GET每段视频的地点为右侧红框圈起来的部分。

百度后才知道,整个视频如何分段是由一个m3u8文件来决定的。m3u8文件中的内容如下所示,记录了每段视频start和end的编号。
  1. #EXTM3U
  2. #EXT-X-VERSION:3
  3. #EXT-X-ALLOW-CACHE:YES
  4. #EXT-X-TARGETDURATION:10
  5. #EXTINF:10.000000,
  6. start_0-end_765064-record.gv.ts
  7. #EXTINF:10.000000,
  8. start_765064-end_1769567-record.gv.ts
  9. #EXTINF:10.000000,
  10. start_1769567-end_2600798-record.gv.ts
  11. #EXTINF:10.000000,
  12. start_2600798-end_3593502-record.gv.ts
  13. #EXTINF:10.000000,
  14. start_3593502-end_4500784-record.gv.ts
  15. #EXTINF:10.000000,
  16. start_4500784-end_5399861-record.gv.ts
  17. #EXTINF:10.000000,
  18. start_5399861-end_6288622-record.gv.ts
  19. #EXTINF:10.000000,
  20. start_6288622-end_7044459-record.gv.ts
  21. #EXTINF:10.000000,
  22. start_7044459-end_7878487-record.gv.ts
  23. #EXTINF:10.000000,
  24. start_7878487-end_8811793-record.gv.ts
  25. #EXTINF:10.000000,
复制代码
因此,下载视频的关键是获取m3u8文件,通过这个视频的m3u8文件来分段下载视频。
我是人工找出m3u8的下载地点,暂时还没研究出来怎么通过视频地点自动剖析出m3u8地点。找的方法很简朴,还是在Chrome的Network控制台找。打开Network控制台,革新页面,就可以找到如图所示的m3u8文件。查看m3u8文件的相干信息,可以看到红框圈起来的地点就是这个视频的m3u8下载地点。

对比两个地点,可以发现文件名前的地点相同,视频下载地点即为"标红地点"+"m3u8文件中列出的视频段文件名":
https://bcdn.enetedu.com/conv/cdnfile/video/2016_06_27/1467034852884_f5821b/hi/record.m3u8
https://bcdn.enetedu.com/conv/cdnfile/video/2016_06_27/1467034852884_f5821b/hi/start_643887-end_1083181-record.gv.ts
因此可以将这部分地点设为:urlroot = https://bcdn.enetedu.com/conv/cdnfile/video/2016_06_27/1467034852884_f5821b/hi
为了方便下载其他视频时动态修改,改为动态截取:
  1. url = input("请输入m3u8文件地址:")
  2. urlRoot=self.url[0:url.rindex('/')]
复制代码
2.批量下载ts视频片断

这一步使用上一步拼接的地点循环下载ts视频即可。下载时,使用登录时创建的session下载。
session是会话的意思,它可以让服务器“认得”客户端。简朴理解就是,把每一个客户端和服务器的互动看成一个“会话”。既然在同一个“会话”里,服务器自然就能知道这个客户端是否登录过。代码如下:
  1. client = requests.Session()
  2. client.post(PostUrl,postData) #登录
  3. resp = client.get(download_path) #下载
复制代码
碎片拼接的方法:下载完第一个ts片断后,直接在该文件后面继承写第二个ts片断,以此类推。而不是新建一个文件写入。与验证码登录联合起来,完备代码如下:
  1. import requests
  2. from PIL import Image
  3. import sys
  4. import m3u8
  5. import time
  6. import os
  7. #用户名-密码-验证码方式,登录
  8. CaptchaUrl = "https://per.enetedu.com/Common/CreateImage" #获取验证码地址
  9. PostUrl = "https://per.enetedu.com/AdminIndex/LoginDo"  #post登录信息地址
  10. client = requests.Session()
  11. username = '526257482@qq.com'
  12. password = 'dashuju_9514'
  13. qr_code = client.get(CaptchaUrl)
  14. open('login.jpg', 'wb').write(qr_code.content) #将验证码图片保存至本地
  15. img = Image.open('login.jpg')
  16. img.show()  #打开图片
  17. code = input("请输入验证码: \n") #输入验证码
  18. postData = { #构造POST表单
  19. 'email': username,
  20. 'pwd': password,
  21. 'validateCode': code,
  22. 'x': '56',
  23. 'y': '19'
  24. }
  25. result = client.post(PostUrl,postData) #向PostUrl提交表单
  26. #循环下载ts视频
  27. class VideoCrawler():
  28. def __init__(self,url):
  29.   super(VideoCrawler, self).__init__()
  30.   self.url=url
  31.   self.final_path=r"D:\Download\Film"
  32.   
  33. #下载并解析m3u8文件
  34. def get_url_from_m3u8(self,readAdr):
  35.   print("正在解析真实下载地址...")
  36.   with open('temp.m3u8','wb') as file:
  37.    file.write(requests.get(readAdr).content)
  38.   m3u8Obj=m3u8.load('temp.m3u8')
  39.   print("解析完成")
  40.   return m3u8Obj.segments
  41. def run(self):
  42.   print("Start!")
  43.   start_time=time.time()
  44.   realAdr = self.url #m3u8下载地址
  45.   urlList=self.get_url_from_m3u8(realAdr) #解析m3u8文件,获取下载地址
  46.   urlRoot=self.url[0:self.url.rindex('/')]
  47.   i=1
  48.   outputfile=open(os.path.join(self.final_path,'%s.ts'%self.fileName),'wb')#初始创建一个ts文件,之后每次循环将ts片段的文件流写入此文件中从而不需要在去合并ts文件
  49.   
  50.   for url in urlList:
  51.    try:   
  52.     download_path = "%s/%s" % (urlRoot, url.uri) #拼接地址
  53.     resp = client.get(download_path) #使用拼接地址去爬取数据
  54.     progess = i/len(urlList)#记录当前的爬取进度
  55.     outputfile.write(resp.content) #将爬取到ts片段的文件流写入刚开始创建的ts文件中
  56.     sys.stdout.write('\r正在下载:{},进度:{:.2%}'.format(self.fileName,progess))#通过百分比显示下载进度
  57.     sys.stdout.flush()#通过此方法将上一行代码刷新,控制台只保留一行
  58.    except Exception as e:
  59.     print("\n出现错误:%s",e.args)
  60.     continue#出现错误跳出当前循环,继续下次循环
  61.    i+=1
  62.   outputfile.close()
  63.   print("下载完成!总共耗时%d s"%(time.time()-start_time))
  64.   print("开始转换视频格式!")
  65.   success = os.system(r'copy /b D:\Download\Film\{0}.ts D:\Download\Film\{0}.mp4'.format(self.fileName)) #ts转成mp4格式
  66.   if (not success):
  67.    print("格式转换成功!")
  68.    os.remove(self.final_path+'\\'+self.fileName+".ts") #删除ts和m3u8临时文件
  69.    os.remove("temp.m3u8")
  70. if __name__=='__main__':
  71. m3u8_addr = input("输入m3u8文件下载地址:\n")
  72. crawler=VideoCrawler(m3u8_addr)
  73. crawler.fileName = input("输入文件名:\n")
  74. crawler.run()
  75. quitClick=input("请按Enter键确认退出!")
复制代码
三、总结

代码可以实现分段加载视频的爬取功能,此中还有很多细节待美满如:
      
  • 验证码可以通过图像辨认的方法自动辨认。  
  • 通过剖析视频地点获取m3u8文件,非盘算机专业人使用起来更加友好。  
  • 例子中的网站没有对m3u8文件举行加密,涉及到加密的m3u8还必要加一步解密的过程。
到此这篇关于Python爬虫爬取ts碎片视频+验证码登录功能的文章就介绍到这了,更多相干Python爬虫爬取视频内容请搜索脚本之家从前的文章或继承欣赏下面的相干文章渴望各人以后多多支持脚本之家!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作