爬取视频的总结

当时看到了与fate有关的视频感觉挺不错的,所以想把这些视频爬取下来。于是做了一个脚本进行爬取,废话不说上的代码。
1.网页分析
本次爬取数据来源与一个网站:
布米米
http://www.bumimi66.com/
网站内容还挺全的,里面基本上什么视频都有。
这里我们对其中一个视频进行分析
http://www.bumimi66.com/acg/2641/3.html
视频内容一般是动态加载的,对于动态加载的数据我们有
四种获取方法:
1.通过selenium来获取动态页面源码
2.xhr数据(json包,xhr包)
3.js数据
4.通过观察url的规律来获取
这里我们直接尝试抓包工具
打开抓包工具发现:


发现了这两个包,易知media包是由js包动态加载出来的并且js包也好拼接,所以我们选择js包进行获取
http://t.mtyee.com/ne2/s2641.js?1607175419
观察网页ur=http://www.bumimi66.com/acg/2641/3.html
与js的url,发现js网址是由前面的“http://t.mtyee.com/ne2/s+网页中acg/后的一段数字+.js?+任意数字 ”构成的。所以我们可以通过视频url,拼接出js的url。
有获取视频链接的函数:

def video_list(url_split,begin,end):list1=[]list4=[]list5=[]#利用正则获取网页中acg/后的一段数字p2 = re.compile(r'/([\d]+)/', re.S)url1 = re.findall(p2, url_split)[0]#拼接urlurl = 'http://t.mtyee.com/ne2/s' + url1 + '.js?123'#获取url的响应数据response = requests.get(url=url).text#这里提取分为两种情况:#在爬取的过程:有mp4格式的数据和m3u8格式的数据,用正则进行提取p1 = re.compile(r'"(https://[\w].+?[mp4,m3u8]),', re.S)#这里正则提取时出了一些问题:就是这个js数据里面有很多源的数据,十分有可能提取出多个代表一个视频的url所以有了list3就是提取http:后面的一段代表不同网址的数据p2=re.compile(r'https://(.+?)/',re.S)list2=re.findall(p1, response)list3=re.findall(p2,list2[0])print(list3[0])for i in range(len(list2)):#检验list3所代表的不同网址数据是否在list2的每个元里面if list3[0] in str(list2[i]):list4.append(list2[i])print(list4)print(begin,end)#这是提取指定集数的一个小小的封装for循环for i in range(int(begin),int(end)+1):list5.append(list4[int(i)])print('总共有' + str(len(list5)) + '集')return list5

还有就是搜索函数,这个很容易看到,不同的我们无法通过我们想爬取的内容,来获取指定的url,所以我们需要找一个跳板
这里我们看中了搜索页面:
http://www.bumimi66.com/search/%E9%AD%94%E6%B3%95%E5%B0%91%E5%A5%B3%E4%BC%8A%E8%8E%89%E9%9B%85
发现search/后面解码后就是我们搜索的内容,并且这个页面中也有我们获得的url,这里还是打开抓包工具找到json栏,这里笔者遭到了一些阻塞,就是每回用requests获取json数据时,发现403报错(服务器禁止访问),经过检查后发现是请求头的问题:

加入请求头:
有获取页面数据的函数:

def inf_get(url):#加一个请求头就可以获取数据,并且获取当前页面所有信息,并且返回一个列表(里面是字典)#得到此页面的url,封面url,标题,出版时间,演员等list=[]header={'Accept': '*/*','Accept-Encoding': 'gzip, deflate','Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6','Connection': 'keep-alive','Host': '118.89.59.239:8800','Origin': 'http://www.bumimi77.com','Referer': 'http://www.bumimi77.com/','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66',}response = requests.get(url=url,headers=header)#c=response[6:len(str(response))-1]response.encoding='utf-8'str_inf=response.text#print(str_inf)#用正则表达式提取括号内容p1 = re.compile(r'[{](.*?)[}]', re.S)for i in re.findall(p1, str_inf):#转化出来的没有外面括号。加上括号,使用json.load方法list_transf='{'+i+'}'list.append(json.loads(list_transf))return list
def page_inf(url):                #这个函数的作用是封装你爬取的视频的信息的url(最主要是集数),和返回储存爬取的url的列表list=[]                          #获取响应数据的urlheader={'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9','Accept-Encoding': 'gzip, deflate','Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6','Cache-Control': 'max-age=0','Connection': 'keep-alive','Cookie': 'PHPSESSID=p05d88u2h4f12elggcfgifsvv5; y_Cookie_v=%E9%AD%94%E6%B3%95%E5%B0%91%E5%A5%B3%E4%BC%8A%E8%8E%89%E9%9B%85%E7%AC%AC%E4%B8%89%E5%AD%A33%20%E9%AD%94%E6%B3%95%E5%B0%91%E5%A5%B3%E4%BC%8A%E8%8E%89%E9%9B%85%E7%AC%AC%E4%B8%89%E5%AD%A3%20%E7%AC%AC3%E9%9B%86%20%E5%9C%A8%E7%BA%BF%E8%A7%82%E7%9C%8B%20-%20%E5%B8%83%E7%B1%B3%E7%B1%B3%40http%3A%2F%2Fwww.bumimi77.com%2Facg%2F2641%2F3.html%24%401609341680; Hm_lvt_3ce85e1f6a94e19a4aa54b75941d61e9=1609341681; y_Cookie_v_search=%E9%AD%94%E6%B3%95%E5%B0%91%E5%A5%B3%E4%BC%8A%E8%8E%89%E9%9B%85%40http%3A%2F%2Fwww.bumimi77.com%2Fsearch%2F%25E9%25AD%2594%25E6%25B3%2595%25E5%25B0%2591%25E5%25A5%25B3%25E4%25BC%258A%25E8%258E%2589%25E9%259B%2585%24%401609381969; Hm_lpvt_3ce85e1f6a94e19a4aa54b75941d61e9=1609381976','Host': 'www.bumimi77.com','Referer': 'http://www.bumimi77.com/search/%E9%AD%94%E6%B3%95%E5%B0%91%E5%A5%B3%E4%BC%8A%E8%8E%89%E9%9B%85','Upgrade-Insecure-Requests': '1','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66',}response = requests.get(url=url, headers=header).texthtml = etree.HTML(response)try:if html.xpath('//*[@id="qiyi-pl-list"]/div/ul/li[1]/a/@href'):rec = html.xpath('//*[@id="qiyi-pl-list"]/div/ul/li[1]/a/@href')[0]p1=re.compile(r'([\d]+)')c=re.findall(p1,rec)print(c[0])print('总共有'+c[0]+'集')for i in range(0,int(c[0])):list.append(url+str(i)+'.html')return listexcept:print("这个网页不能爬取或者是没有你想要的信息")pass

视频的保存
来到了重点视频的保存:
视频的保存有两种形式mp4,m3u8,MP4形式的视频好处理,直接调用you-get模块即可
python(you-get):2分钟快速下载网站视频
而对于m3u8格式的下载笔者查阅了大量的资料终于搞懂了他其中的机制
Python下载加密m3u8视频
python-m3u8-协程-快速下载并合并MP4
【python爬虫】爬取网页视频,解析m3u8文件,获取ts并合成mp4
这里有m3u8的下载链接:https://mei.huazuida.com/20191021/11051_c691e197/index.m3u8

得到一个m3u8格式的文件,用记事本打开该文件
有这样内容:
根据资料查阅知:这个m3u8是第一层url,需要通过url拼接获得第二层url,把最后一行加上第一个url得第二个url
https://mei.huazuida.com/20191021/11051_c691e197/1000k/hls/index.m3u8
下载第二个url,用记事本打开

得出第二个url内容,可以根据其合成ts的url
https://mei.huazuida.com/20191021/11051_c691e197/1000k/hls/602967b17ac000001.ts
然后我们可以获取每个ts片段,并且用系统中copy命令合并
代码如下:

def m3u8_download(url,path,video_num):def download1(url):download_path = os.getcwd() + "\download"if not os.path.exists(download_path):os.mkdir(download_path)# 新建日期文件夹download_path = os.path.join(download_path, datetime.datetime.now().strftime('%Y%m%d_%H%M%S'))# print download_pathos.mkdir(download_path)response=requests.get(url=url).textp1=re.compile(r'(.*/.+/.*\.m3u8)')p2=re.compile(r'(https://.+)index\.m3u8')p3=re.compile(r'.*?\.ts')inf=re.findall(p1,response)[0]inf2=re.findall(p2,url)[0]url2=inf2+infinf4=re.findall(p2,url2)[0]response1=requests.get(url=url2).textinf3=re.findall(p3,response1)#path='C:/Users/mzy/Desktop/新建文件夹'num = 0for line in inf3:  # 第二层url3=inf4+str(line)c=0while c!=1:try:if requests.get(url=url3):res=requests.get(url=url3)print(url3)with open(os.path.join(download_path,line), 'ab') as f:f.write(res.content)f.flush()c=1num=num+1print(num / len(inf3) * 100)except:print("error")passprint("下载完成")merge_file(download_path)

然后我们开始下载,发现下载太慢了,大约一下午才下了一集,(虽说很大部分是河南某211网络巨差),于是我们可以尝试一波线程池:

 def merge_file(path,video_num):  #合并ts文件os.chdir(path)cmd = "copy /b * new.tmp"os.system(cmd)os.system('del /Q *.ts')os.system('del /Q *.mp4')#now=str(datetime.datetime.now())[11:19]os.rename("new.tmp", "%d.mp4"%video_num)response = requests.get(url=url).textp1 = re.compile(r'(.*/.+/.*\.m3u8)')p2 = re.compile(r'(https://.+)index\.m3u8')p3 = re.compile(r'.*?\.ts')inf = re.findall(p1, response)[0]inf2 = re.findall(p2, url)[0]url2 = inf2 + infinf4 = re.findall(p2, url2)[0]response1 = requests.get(url=url2).textinf3 = re.findall(p3, response1)num = 0filename = path + '/' + str(video_num) + '集'urls=[]for i in inf3:url3 = inf4 + str(i)#print(url3)key={'name':i,'url3':url3}urls.append(key)def get_video_data(url):c = 0url3=url['url3']name=url['name']while c != 1:try:if requests.get(url=url3):c = 1response = requests.get(url=url3)#print(filename)filename1=filename +'/'+ name#print(filename1)#'C:/Users/mzy/Desktop/gangtie/'#检查文件夹是否被建立,建立则停止则证明这一集已经被爬过os.makedirs(os.path.dirname(filename1), exist_ok=True)with open(filename1, "wb") as f:f.write(response.content)f.flush()print(filename1)#print(num / len(inf3) * 100)except:print("error")pass# 使用线程池对视频数据进行请求pool = Pool(100)  # c参数放有几个需要爬取的对象pool.map(get_video_data, urls)# 关闭线程池pool.close()pool.join()merge_file(filename,video_num)print('success')

虽说,速度变快了好几倍,但是,一个代学生怎么会满足与这一点点速度呢,然后笔者,尝试了线程池函数

    def merge_file(path,video_num):  #合并ts文件os.chdir(path)cmd = "copy /b * new.tmp"os.system(cmd)os.system('del /Q *.ts')os.system('del /Q *.mp4')#now=str(datetime.datetime.now())[11:19]os.rename("new.tmp", "%d.mp4"%video_num)response = requests.get(url=url).textp1 = re.compile(r'(.*/.+/.*\.m3u8)')p2 = re.compile(r'(https://.+)index\.m3u8')p3 = re.compile(r'.*?\.ts')inf = re.findall(p1, response)[0]inf2 = re.findall(p2, url)[0]url2 = inf2 + infinf4 = re.findall(p2, url2)[0]response1 = requests.get(url=url2).textinf3 = re.findall(p3, response1)num = 0filename = path + '/' + str(video_num) + '集'urls = []for i in inf3:url3 = inf4 + str(i)# print(url3)key = {'name': i,'url3': url3}urls.append(key)async def get_page(url):url3 = url['url3']name = url['name']c = 0# get与post函数一样,可以添加headers和,params/data参数,但是代理ip时,要换参数:proxy后面加入字典非字符串while c != 1:try:filename1 = filename + '/' + nameos.makedirs(os.path.dirname(filename1), exist_ok=True)async with aiohttp.ClientSession() as session:async with await session.get(url3) as response:# text()返回字符串形式的响应数据# read()返回的二进制形式的响应数据# json()返回的就是json对象# 注意:湖区响应数据前一定要用await挂起page_text = await response.read()with open(filename1, "wb") as f:f.write(page_text)f.flush()print(filename1, 'success')c = 1except:print(url3, "error")pass#异步爬取部分tasks = []for url in urls:task_temp = get_page(url)task = asyncio.ensure_future(task_temp)tasks.append(task)loop = asyncio.get_event_loop()loop.run_until_complete(asyncio.wait(tasks))#loop.close()merge_file(filename,video_num)print('success')

速度是几倍,完美。
然后这里附上,笔者初学多线程的笔记

# #在爬虫中使用异步实现高性能的数据爬取操作
# #异步爬虫的方法:
# #多线程,
# #可以为相关的操作单独开启线程
# #使用线程池的方式执行
# #线程池的爬取原则:线程池处理的阻塞且耗时的操作
#
#
# ###############################
# #导入模块
# # import time
# # import re
# # from lxml import etree
# # import requests
# # from multiprocessing.dummy import Pool
# # url="https://www.bilibili.com/v/kichiku/"
# # headers={# # "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Edg/87.0.664.75"
# # }
# # page_text=requests.get(url=url,headers=headers).text
# # html=etree.HTML(page_text)
# #注意这一步定位不到xpath是因为他是动态加载的,需要用抓包工具找js,xhr,php,甚至用selenium来获去数据这里只是想说一下另类的xpath定位的方法
# #通过要把xpath,re,beautifulsoup理解成一个文本处理的库,不过特殊在他们处理的是html数据
# #如果有一个模型,一个大的div里面有很多小的a标签(里面的src的属性值是我们要的),
# #可以先定位这个这个大的div,然后后面加入/a,这表示的是定位大的div里面所有的a标签有,返回一个列表
# #列表循环,对每个返回的list值用xpath定位
# #然后在用xpath定位其相对的路径用./@src来定位src的属性值
# #############################测试代码#######################################################
# # url_list=html.xpath('//*[@id="kichiku_guide"]/div[2]/div[1]/div[2]/div[1]/a')
# # print(url_list)
# # with open('url.html','w',encoding='utf-8') as fp:
# #     fp.write(page_text)
# #########################################################################################
# #正则永远的神xpath,beautifulsoup定位不到的正则能提取
# #selenium得出的源码数据,xpath,beautifulsoup处理不了测,正则能提取
# #正则yyds
# ################################线程池的使用###########################################################
# # from multiprocessing.dummy import Pool
# # #放入需要爬取的url
# # urls=[]
# # #定义线程池函数
# import requests
# def get_video_data(url):
#     data=requests.get(url=url).content
#     #持久化存储操作
#     with open("url"+'.html','wb') as fp:
#         fp.write(data)
#         print("下载完成")
# get_video_data('https://www.bilibili.com/v/kichiku/guide/#/all/click/0/1/2020-1-01,2021-01-01')
# # #使用线程池对视频数据进行请求
# # pool=Pool(4)  #c参数放有几个需要爬取的对象
# # pool.map(get_video_data,urls)
# # #关闭线程池
# # pool.close()
# # pool.join()
# ###########################################################################
# #单线程+异步协程
# #event_loop:事件循环,相当于无限循环,我们可以将一些函数注册到这个事件循环中,当满足某些条件则会执行
# #coroutine:协程对象,我们可以将协程对象注册到事件循环中,它会被事件循环调用,我们可以使用async关键字来定义一个方法,这个方法在调用时不会立刻执行,
# #而是返回协程对象
# #task:任务,它是对协程的进一步封装,包含了任务的各个状态
# #future:代表将来执行或者还没有执行的任务,本质和task一样
# #async定义一个协程
# #awit用来挂起阻塞方法的执行
# #########################################################################
# # import asyncio
# # import time
# # async def request(url):
# #     print("正在下载",url)
# #     #在异步协程中出现了同步模块相关的代码,那么就无法实现异步
# #     #time.sleep(2)
# #     #当asynico中遇到阻塞操作必须手动挂起
# #     #一下代码代表time.sleep(2)
# #     await asyncio.sleep(2)
# #     print("下载完毕",url)
# # urls=[
# #     'a',
# #     'b',
# #     'c'
# # ]
# # stasks=[]
# # for url in urls:
# #     c=request(url)
# #     #把c函数封装成协程任务
# #     task=asyncio.ensure_future(c)
# #     #把协程任务封装到stasks列表中
# #     stasks.append(task)
# # #封装线程池
# # loop=asyncio.get_event_loop()
# # #固定格式,将任务列表储存在wait函数中
# # loop.run_until_complete(asyncio.wait(stasks))
# #######################################################################################
# ##异步函数中不能出现同步模块代码
# #我们可以通过aiohttp:模块 来实现网路的请求
# #使用该模块中clientsession来实现异步爬取
#
# import aiohttp
# import asyncio
# import os
# import requests
# import re
# response = requests.get(url=url).text
# p1 = re.compile(r'(.*/.+/.*\.m3u8)')
# p2 = re.compile(r'(https://.+)index\.m3u8')
# p3 = re.compile(r'.*?\.ts')
# inf = re.findall(p1, response)[0]
# inf2 = re.findall(p2, url)[0]
# url2 = inf2 + inf
# inf4 = re.findall(p2, url2)[0]
# response1 = requests.get(url=url2).text
# inf3 = re.findall(p3, response1)
# num = 0
# filename = path + '/' + str(video_num) + '集'
# urls = []
# for i in inf3:
#     url3 = inf4 + str(i)
#     # print(url3)
#     key = {#         'name': i,
#         'url3': url3
#     }
#     urls.append(key)
# async def get_page(url):
#     url3 = url['url3']
#     name = url['name']
#     c=0
# #get与post函数一样,可以添加headers和,params/data参数,但是代理ip时,要换参数:proxy后面加入字典非字符串
#     while c!=1:
#         try:
#             filename1 = filename + '/' + name
#             os.makedirs(os.path.dirname(filename1), exist_ok=True)
#             async with aiohttp.ClientSession() as session:
#                 async with await session.get(url3) as response:
#                     #text()返回字符串形式的响应数据
#                     #read()返回的二进制形式的响应数据
#                     #json()返回的就是json对象
#                     #注意:湖区响应数据前一定要用await挂起
#                     page_text=await response.read()
#                     with open(filename1, "wb") as f:
#                         f.write(page_text)
#                         f.flush()
#                         print(filename1,'success')
#                         c=0
#         except:
#             print(url3,"error")
#             pass
# tasks=[]
# for url in urls:
#     task_temp=get_page(url)
#     task=asyncio.ensure_future(task_temp)
#     tasks.append(task)
# loop=asyncio.get_event_loop()
# loop.run_until_complete(asyncio.wait(tasks))
#

在来个函数来封装下载方法:

def download(url, path,video_num):print("hello")if '.mp4' in url:sys.argv = ['you-get', '-o', path, url]you_get.main()print("hello")elif '.m3u8' in url:m3u8_download(url,path,video_num)else:print(url)print('这个视频下载不了请复制页面在浏览器上下载')

最后来个main_f函数来封装:

def main_in():num=0list1=[]    #的到url转页面的网址list2=[]    #得到封面list3=[]     #得到名字quest=input("你要爬取的页面:")quest1=quote(quest)print(quest1)url='http://159.75.7.49:7211/sssv.php?top=10&q='+quest1#download(url, path)for i in inf_get(url):#得到页面中的字典list1.append(i['url'])list2.append(i['title'])#list3.append(i['thumb'])         #保存封面的函数回来在封装print("总共%d条信息"%len(list2))while num<len(list2):while True:print(list2[num])path = 'C:/Users/mzy/Desktop/'+list2[num]  # 保存目录,没有则建立c=input("你要爬取这个页面么?(1表示是,0表示否)")page_inf(list1[num])if c=='1':begin = input("你要获取第几集到第几集的信息:(开头)")end = input("你要获取第几集到第几集的信息:(结尾)")#page_inf(list1[num],begin,end)num1=int(begin)for k in video_list(list1[num],begin,end):print(str(k))download(k,path,num1)num = num + 1num1=num1+1elif c=='0':num = num + 1break#魔法少女伊莉雅else:print('inputerror')

最后总的代码如下:

import sys
import os
import re
import you_get
import requests
import json
import datetime
import asyncio
import aiohttp
from lxml import etree
from urllib.parse import unquote,quote
from multiprocessing.dummy import Pool
from Crypto.Cipher import AES
from time import sleep
from tqdm import tqdm
def m3u8_download(url,path,video_num):#########################单线程方法######################################## def download1(url):#     download_path = os.getcwd() + "\download"#     if not os.path.exists(download_path):#         os.mkdir(download_path)##     # 新建日期文件夹#     download_path = os.path.join(download_path, datetime.datetime.now().strftime('%Y%m%d_%H%M%S'))#     # print download_path#     os.mkdir(download_path)#     response=requests.get(url=url).text#     p1=re.compile(r'(.*/.+/.*\.m3u8)')#     p2=re.compile(r'(https://.+)index\.m3u8')#     p3=re.compile(r'.*?\.ts')#     inf=re.findall(p1,response)[0]#     inf2=re.findall(p2,url)[0]#     url2=inf2+inf#     inf4=re.findall(p2,url2)[0]#     response1=requests.get(url=url2).text#     inf3=re.findall(p3,response1)#     #path='C:/Users/mzy/Desktop/新建文件夹'#     num = 0#     for line in inf3:  # 第二层#         url3=inf4+str(line)#         c=0#         while c!=1:#             try:#                 if requests.get(url=url3):#                     res=requests.get(url=url3)#                     print(url3)#                     with open(os.path.join(download_path,line), 'ab') as f:#                         f.write(res.content)#                         f.flush()#                         c=1#                         num=num+1#                         print(num / len(inf3) * 100)#             except:#                 print("error")#                 pass#     print("下载完成")#     merge_file(download_path)## def merge_file(path):#     os.chdir(path)#     cmd = "copy /b * new.tmp"#     os.system(cmd)#     os.system('del /Q *.ts')#     os.system('del /Q *.mp4')#     os.rename("new.tmp", "new.mp4")## download1(url)##########################线程池方法############################ def merge_file(path,video_num):  #合并ts文件#     os.chdir(path)#     cmd = "copy /b * new.tmp"#     os.system(cmd)#     os.system('del /Q *.ts')#     os.system('del /Q *.mp4')#     #now=str(datetime.datetime.now())[11:19]#     os.rename("new.tmp", "%d.mp4"%video_num)# response = requests.get(url=url).text# p1 = re.compile(r'(.*/.+/.*\.m3u8)')# p2 = re.compile(r'(https://.+)index\.m3u8')# p3 = re.compile(r'.*?\.ts')# inf = re.findall(p1, response)[0]# inf2 = re.findall(p2, url)[0]# url2 = inf2 + inf# inf4 = re.findall(p2, url2)[0]# response1 = requests.get(url=url2).text# inf3 = re.findall(p3, response1)# num = 0# filename = path + '/' + str(video_num) + '集'# urls=[]# for i in inf3:#     url3 = inf4 + str(i)#     #print(url3)#     key={#         'name':i,#         'url3':url3#     }#     urls.append(key)# # 定义线程池函数# def get_video_data(url):#     c = 0#     url3=url['url3']#     name=url['name']#     while c != 1:#         try:#             if requests.get(url=url3):#                 c = 1#                 response = requests.get(url=url3)#                 #print(filename)#                 filename1=filename +'/'+ name#                 #print(filename1)#                 #'C:/Users/mzy/Desktop/gangtie/'#                 #检查文件夹是否被建立,建立则停止则证明这一集已经被爬过#                 os.makedirs(os.path.dirname(filename1), exist_ok=True)#                 with open(filename1, "wb") as f:#                     f.write(response.content)#                     f.flush()#                     print(filename1)#                 #print(num / len(inf3) * 100)#         except:#             print("error")#             pass# # 使用线程池对视频数据进行请求# pool = Pool(100)  # c参数放有几个需要爬取的对象# pool.map(get_video_data, urls)# # 关闭线程池# pool.close()# pool.join()# merge_file(filename,video_num)# print('success')###########################多任务异步协程方法#####################################def merge_file(path,video_num):  #合并ts文件os.chdir(path)cmd = "copy /b * new.tmp"os.system(cmd)os.system('del /Q *.ts')os.system('del /Q *.mp4')#now=str(datetime.datetime.now())[11:19]os.rename("new.tmp", "%d.mp4"%video_num)response = requests.get(url=url).textp1 = re.compile(r'(.*/.+/.*\.m3u8)')p2 = re.compile(r'(https://.+)index\.m3u8')p3 = re.compile(r'.*?\.ts')inf = re.findall(p1, response)[0]inf2 = re.findall(p2, url)[0]url2 = inf2 + infinf4 = re.findall(p2, url2)[0]response1 = requests.get(url=url2).textinf3 = re.findall(p3, response1)num = 0filename = path + '/' + str(video_num) + '集'urls = []for i in inf3:url3 = inf4 + str(i)# print(url3)key = {'name': i,'url3': url3}urls.append(key)async def get_page(url):url3 = url['url3']name = url['name']c = 0# get与post函数一样,可以添加headers和,params/data参数,但是代理ip时,要换参数:proxy后面加入字典非字符串while c != 1:try:filename1 = filename + '/' + nameos.makedirs(os.path.dirname(filename1), exist_ok=True)async with aiohttp.ClientSession() as session:async with await session.get(url3) as response:# text()返回字符串形式的响应数据# read()返回的二进制形式的响应数据# json()返回的就是json对象# 注意:湖区响应数据前一定要用await挂起page_text = await response.read()with open(filename1, "wb") as f:f.write(page_text)f.flush()print(filename1, 'success')c = 1except:print(url3, "error")pass#异步爬取部分tasks = []for url in urls:task_temp = get_page(url)task = asyncio.ensure_future(task_temp)tasks.append(task)loop = asyncio.get_event_loop()loop.run_until_complete(asyncio.wait(tasks))#loop.close()merge_file(filename,video_num)print('success')
def download(url, path,video_num):print("hello")if '.mp4' in url:sys.argv = ['you-get', '-o', path, url]you_get.main()print("hello")elif '.m3u8' in url:m3u8_download(url,path,video_num)else:print(url)print('这个视频下载不了请复制页面在浏览器上下载')
#注意:有些网址下不了例如魔法少女莉莉娅剧场版只有网址但拒绝下载,可以用selenium来解决等明年有时间在尝试
def inf_get(url):#加一个请求头就可以获取数据,并且获取当前页面所有信息,并且返回一个列表(里面是字典)#得到此页面的url,封面url,标题,出版时间,演员等list=[]header={'Accept': '*/*','Accept-Encoding': 'gzip, deflate','Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6','Connection': 'keep-alive','Host': '118.89.59.239:8800','Origin': 'http://www.bumimi77.com','Referer': 'http://www.bumimi77.com/','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66',}response = requests.get(url=url,headers=header)#c=response[6:len(str(response))-1]response.encoding='utf-8'str_inf=response.text#print(str_inf)#用正则表达式提取括号内容p1 = re.compile(r'[{](.*?)[}]', re.S)for i in re.findall(p1, str_inf):#转化出来的没有外面括号。加上括号,使用json.load方法list_transf='{'+i+'}'list.append(json.loads(list_transf))return list
def page_inf(url):                #这个函数的作用是封装你爬取的视频的信息的url(最主要是集数),和返回储存爬取的url的列表list=[]                          #获取响应数据的urlheader={'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9','Accept-Encoding': 'gzip, deflate','Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6','Cache-Control': 'max-age=0','Connection': 'keep-alive','Cookie': 'PHPSESSID=p05d88u2h4f12elggcfgifsvv5; y_Cookie_v=%E9%AD%94%E6%B3%95%E5%B0%91%E5%A5%B3%E4%BC%8A%E8%8E%89%E9%9B%85%E7%AC%AC%E4%B8%89%E5%AD%A33%20%E9%AD%94%E6%B3%95%E5%B0%91%E5%A5%B3%E4%BC%8A%E8%8E%89%E9%9B%85%E7%AC%AC%E4%B8%89%E5%AD%A3%20%E7%AC%AC3%E9%9B%86%20%E5%9C%A8%E7%BA%BF%E8%A7%82%E7%9C%8B%20-%20%E5%B8%83%E7%B1%B3%E7%B1%B3%40http%3A%2F%2Fwww.bumimi77.com%2Facg%2F2641%2F3.html%24%401609341680; Hm_lvt_3ce85e1f6a94e19a4aa54b75941d61e9=1609341681; y_Cookie_v_search=%E9%AD%94%E6%B3%95%E5%B0%91%E5%A5%B3%E4%BC%8A%E8%8E%89%E9%9B%85%40http%3A%2F%2Fwww.bumimi77.com%2Fsearch%2F%25E9%25AD%2594%25E6%25B3%2595%25E5%25B0%2591%25E5%25A5%25B3%25E4%25BC%258A%25E8%258E%2589%25E9%259B%2585%24%401609381969; Hm_lpvt_3ce85e1f6a94e19a4aa54b75941d61e9=1609381976','Host': 'www.bumimi77.com','Referer': 'http://www.bumimi77.com/search/%E9%AD%94%E6%B3%95%E5%B0%91%E5%A5%B3%E4%BC%8A%E8%8E%89%E9%9B%85','Upgrade-Insecure-Requests': '1','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66',}response = requests.get(url=url, headers=header).texthtml = etree.HTML(response)try:if html.xpath('//*[@id="qiyi-pl-list"]/div/ul/li[1]/a/@href'):rec = html.xpath('//*[@id="qiyi-pl-list"]/div/ul/li[1]/a/@href')[0]p1=re.compile(r'([\d]+)')c=re.findall(p1,rec)print(c[0])print('总共有'+c[0]+'集')for i in range(0,int(c[0])):list.append(url+str(i)+'.html')return listexcept:print("这个网页不能爬取或者是没有你想要的信息")pass
def video_list(url_split,begin,end):#3124list1=[]list4=[]list5=[]p2 = re.compile(r'/([\d]+)/', re.S)url1 = re.findall(p2, url_split)[0]#print(url1)url = 'http://t.mtyee.com/ne2/s' + url1 + '.js?123'response = requests.get(url=url).text#print(response)# p1 = re.compile(r'"(http+.*?)"', re.S)p1 = re.compile(r'"(https://[\w].+?[mp4,m3u8]),', re.S)p2=re.compile(r'https://(.+?)/',re.S)list2=re.findall(p1, response)list3=re.findall(p2,list2[0])print(list3[0])for i in range(len(list2)):if list3[0] in str(list2[i]):list4.append(list2[i])print(list4)print(begin,end)for i in range(int(begin),int(end)+1):list5.append(list4[int(i)])print('总共有' + str(len(list5)) + '集')return list5
def main_in():num=0list1=[]    #的到url转页面的网址list2=[]    #得到封面list3=[]     #得到名字quest=input("你要爬取的页面:")quest1=quote(quest)print(quest1)url='http://159.75.7.49:7211/sssv.php?top=10&q='+quest1#download(url, path)for i in inf_get(url):#得到页面中的字典list1.append(i['url'])list2.append(i['title'])#list3.append(i['thumb'])         #保存封面的函数回来在封装print("总共%d条信息"%len(list2))while num<len(list2):while True:print(list2[num])path = 'C:/Users/mzy/Desktop/'+list2[num]  # 保存目录,没有则建立c=input("你要爬取这个页面么?(1表示是,0表示否)")page_inf(list1[num])if c=='1':begin = input("你要获取第几集到第几集的信息:(开头)")end = input("你要获取第几集到第几集的信息:(结尾)")#page_inf(list1[num],begin,end)num1=int(begin)for k in video_list(list1[num],begin,end):print(str(k))download(k,path,num1)num = num + 1num1=num1+1elif c=='0':num = num + 1break#魔法少女伊莉雅else:print('inputerror')
if __name__ == '__main__':main_in()# file=open("aa.html",'a', encoding='utf-8')#  file.write(response)

补充:
M3U8文件是指UTF-8编码格式的M3U文件。M3U文件是记录了一个索引纯文本文件,打开它时播放软件并不是播放它,而是根据它的索引找到对应的音视频文件的网络地址进行在线播放。

m3u8标签与属性说明
#EXTM3U
每个M3U文件第一行必须是这个tag,请标示作用

#EXT-X-VERSION:3
该属性可以没有

#EXT-X-MEDIA-SEQUENCE:140651513
每一个media URI在PlayList中只有唯一的序号,相邻之间序号+1,
一个media URI并不是必须要包含的,如果没有,默认为0

#EXT-X-TARGETDURATION
指定最大的媒体段时间长(秒)。所以#EXTINF中指定的时间长度必须小于或是等于这
个最大值。这个tag在整个PlayList文件中只能出现一 次(在嵌套的情况下,一般有
真正ts url的m3u8才会出现该tag)

#EXT-X-PLAYLIST-TYPE
提供关于PlayList的可变性的信息,这个对整个PlayList文件有效,是可选的,格式
如下:#EXT-X-PLAYLIST-TYPE::如果是VOD,则服务器不能改变PlayList 文件;
如果是EVENT,则服务器不能改变或是删除PlayList文件中的任何部分,但是可以向该
文件中增加新的一行内容。

#EXTINF
duration指定每个媒体段(ts)的持续时间(秒),仅对其后面的URI有效,title是
下载资源的url

#EXT-X-KEY
表示怎么对media segments进行解码。其作用范围是下次该tag出现前的所有media
URI,属性为NONE 或者 AES-128。NONE表示 URI以及IV(Initialization
Vector)属性必须不存在, AES-128(Advanced EncryptionStandard)表示URI
必须存在,IV可以不存在。

#EXT-X-PROGRAM-DATE-TIME
将一个绝对时间或是日期和一个媒体段中的第一个sample相关联,只对下一个meida
URI有效,格式如#EXT-X-PROGRAM-DATE-TIME:
For example: #EXT-X-PROGRAM-DATETIME:2010-02-19T14:54:23.031+08:00

#EXT-X-ALLOW-CACHE
是否允许做cache,这个可以在PlayList文件中任意地方出现,并且最多出现一次,作
用效果是所有的媒体段。格式如下:#EXT-X-ALLOW-CACHE:

#EXT-X-ENDLIST
表示PlayList的末尾了,它可以在PlayList中任意位置出现,但是只能出现一个,格
式如下:#EXT-X-ENDLIST

https://blog.csdn.net/Ronadlo7/article/details/81029229?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161399303416780271562425%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=161399303416780271562425&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-1-81029229.first_rank_v2_pc_rank_v29&utm_term=m3u8%E6%96%87%E4%BB%B6%E8%AF%A6%E7%BB%86

一个废物大学生对于视频爬取的小小的总结相关推荐

  1. 爬虫入门实战第一站——梨视频视频爬取

    爬虫入门实战第一站--梨视频视频爬取 简介 博主最近重新开始了解爬虫,想以文字方式记录自己学习和操作的过程.本篇文章主要是使用爬虫爬取梨视频网站中的视频并下载到本地,同时将视频简介和视频网站保存在ex ...

  2. Python爬虫系列之抖音热门视频爬取

    Python爬虫系列之抖音热门视频爬取 主要使用requests库以及手机抓包工具去分析接口 该demo仅供参考,已经失效,需要抖音2019年5月最新所有接口请点击这里获取 抖音资源获取接口文档请点击 ...

  3. python B站原视频爬取,最高清晰度爬取。将你喜欢的up主的视频保存下来吧。

    B站原视频爬取,我就不多说直接上代码.直接运行就好. B站是把视频和音频分开.要把2个合并起来使用.这个需要分析才能看出来.然后就是登陆这块是比较难的. import os import re imp ...

  4. Python Fiddler 钉钉PC端群回放视频爬取

    Python Fiddler 钉钉PC端群回放视频爬取 钉钉群里的回放视频被群管理员设置为不能下载,可是有时候又需要这些视频可以方便传阅和打开调倍速等等,而且还可以不用再打开PC端就可以直接看到视频多 ...

  5. python之六间房视频爬取

    六间房小视频地址为js渲染的网页,爬取时需要找到真实的url地址,然后找到其规律,进行翻页爬取. 网页比较简单,代码如下: '''六间房视频爬取''' # 导入第三方库 import requests ...

  6. 如何爬一个网站的数据-免费爬取网站的任意数据软件

    如何爬一个网站的数据?爬取网络数据大家称之为网络爬行 收集页面以创建索引或集合.另一方面,网络抓取下载页面以提取一组特定的数据用于分析目的,例如,产品详细信息.定价信息.SEO 数据或任何其他数据集. ...

  7. 利用python爬取知乎评论_一个简单的python爬虫,爬取知乎

    一个简单的python爬虫,爬取知乎 主要实现 爬取一个收藏夹 里 所有问题答案下的 图片 文字信息暂未收录,可自行实现,比图片更简单 具体代码里有详细注释,请自行阅读 项目源码: 1 # -*- c ...

  8. Python 视频爬取与存储

    可以把视频存到本地,前提是有视频链接,有的还要登录,我还不会/(ㄒoㄒ)/~~. 这里爬取的是MOOC上的视频,也是我学习的地方. 将链接保存在.py文件同目录下的.txt里即可 import req ...

  9. 【python爬虫】对喜马拉雅上一个专辑的音频进行爬取并保存到本地

    >>>内容基本框架: 1.爬虫目的 2.爬取过程 3.代码实现 4.爬取结果  >>>实验环境: python3.6版本,pycharm,电脑可上网. [一 爬虫目 ...

  10. python爬取哔哩哔哩视频_Python实现视频爬取下载

    注:源内容来自公众号[python学习开发] 一般情况下我们使用爬虫更多的是对数据或者图片进行爬取,今天在这里和大家分享一下关于使用爬虫技术来进行视频下载的方法,不仅可以方便的下载一些体积小的视频,针 ...

最新文章

  1. 知识图:从图和数据库中获取知识
  2. 国内数十位大佬合作,综述预训练模型的过去、现在与未来
  3. php谈谈你对分布式的理解,简谈关于对分布式处理的理解
  4. (转)fatal error C1853: precompiled header file is from a previous version of the compiler, or the pre
  5. MacOS 12.0.X系统提示“未能装载磁盘映像,错误代码为109”的临时解决方法
  6. 在windows命令行中查询MySQL乱码
  7. VS2013 产品密钥 – 所有版本
  8. 解决在DHCP环境下私自指定IP和私自搭建DHCP服务器的方法
  9. Tomcat 部署多个项目出现错误
  10. Tensorflow训练简单神经网络
  11. cvt公链采用什么结构_好马配好鞍,迈锐宝上全新的CVT变速箱,是什么来头?
  12. 网络协议学习--SOAP协议(二)
  13. 全网无损音乐免费下载!
  14. Android之UiAutomator测试框架源码分析(第二十四篇:ByMatcher相关功能介绍)
  15. linux里的文件怎么复制到移动硬盘,linux数据拷贝复制到移动硬盘的问题
  16. 【问题记录】启动 Navicat 的过程中,遇到:Missing required library sqlite.dll,998
  17. 威纶通触摸屏模板,直接打开就可以用
  18. C语言输出ASCII码表1/2
  19. ArcGIS土地利用动态度与土地利用程度计算(附练习数据下载)
  20. 印象笔记mac版 同步问题_Notability 最佳手写笔记 APP 之一!让 iPad / iPhone 变成工作学习利器...

热门文章

  1. 电脑PHP动画制作画板,Canvas在线画图—简单制作一个画板
  2. Office 2016更新后 Word 2016、Excel 2016、Power 2016、Visio 2016、OneNote 2016图标全部消失问题解决
  3. [ROS学习笔记]ROS中使用激光雷达(RPLIDAR)
  4. 计算机组成原理:扩展操作码技术
  5. java实现类的封装(物体实现椭圆运动)
  6. 【渝粤题库】陕西师范大学800010 经济地理学
  7. 混频器的噪声来源与抑制方法
  8. 教你itunes电脑版怎么下载
  9. 3脚送话器内部电路图_电话机维修送话电路故障
  10. 微信支付宝小程序复制内容到剪贴板功能