hello,小伙伴们,又见面了,距离上一次发布文章的时间,也算是久别重逢了。期间也发生了很多的事情,导致博文断更,也是笔者不愿意的,但是确实是比较忙,不再过多赘述,希望大家能够体谅。
平时不断的在后台收到小伙伴的私信,问是不是不更了,答案当然是否定的,有着这么多人的支持,小编还是要继续努力下去的,再次谢谢大家的支持。
是分享一些爬取数据,图片,音乐,还没怎么分享过爬取过视频的,那么想要爬取视频的话该怎么爬取呢?
其实不管是图片,还是音乐,或者是其他的文档,大部分都是一个文件读写的过程,当然视频也不例外,只是文件的格式不同而已。所以我们也可以试着以常规的手段去尝试下爬取视频,没错还是熟悉的套路与配方,即python常用函数 open() 和 write()。
不过这次略微不同的是我们会使用到 iter_content 来获取请求的原始响应数据,普通情况可以用 r.raw,在初始请求中设置 stream=True ,来获取服务器的原始套接字响应,在这里我们使用 iter_content 更加方便一些,因为requests.get(url) 默认是下载在内存中的,下载完成才存到硬盘上,但Response.iter_content 可以边下载边存硬盘中,所以在这视频下载方面更具有优势。
当然说到 iter_content 的话,不得不提下 chunk_size,因为流式请求就是像流水一样,不是一次过来而是一点一点“流”过来。处理流式数据也是一点一点处理。
而chunk_size会直接返回从当前位置往后读取 chunk_size 大小的文件内容,且迭代响应数据。这避免了立即将内容读入内存以获得较大的响应。chunk_size是它应该读入内存的字节数。chunk_size的类型必须是int或None。None的值将根据流的值发挥不同的作用。
做了引荐与讲解后,那么就开始上我们的主菜了,即目标网站:
https://m.rr.tv/
介于代码偏基础化,且主要知识点做过分析就直接上代码了,具体请看代码:
单线程:
import requests
import json
import re
import os
headers = {
'Referer':'https://m.rr.tv/',#全局设置
'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'
}
ep_list =[]
vod_list = []
def get_vod(url):
response = requests.get(url = url,headers = headers)#请求url
ep= re.compile(r'sid:"(.*?)",')#提取ep链接
ep_list = re.findall(ep,response.text)
vod= re.compile(r'data:\[{id:(.*?),title:"')#提取vod链接
vod_list = re.findall(vod,response.text)
vod= re.compile(r',title:"(.*?)",desc:"')#提取视频标题
vod_name = re.findall(vod,response.text)
ep = 1
os.mkdir('./'+vod_name[0])#创建视频保存目录
for i in ep_list:
print("开始下载"+vod_name[0]+"第"+str(ep)+"集")
url ="https://web-api.rr.tv/web/drama/play?webChannel=M_STATION&dramaId="+vod_list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址
response = requests.get(url = url,headers = headers)#下载请求
r = requests.get(str(json.loads(response.text)['data']['url']), stream=True)#解析出下载链接并发起下载请求
f = open("./"+vod_name[0]+"/第"+str(ep)+"集.MP4", "wb")#保存视频
for chunk in r.iter_content(chunk_size=512):
if chunk:
f.write(chunk)
ep = ep+1
if __name__ == '__main__':
url='https://m.rr.tv/detail/xxxxxx?snum=1&episode=1'#目标视频链接
get_vod(url)
多线程:
import requests
import json
import re
import os
from concurrent.futures import ThreadPoolExecutor
headers = {
'Referer':'https://m.rr.tv/',#全局设置
'User-Agent':'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'
}
vod_list = []#存储视频链接
vod_name = []#存储视频标题
get_down_url =[]#存储下载直链
def get_vod(url):
response = requests.get(url = url,headers = headers)#请求url
vod_list.append(re.findall(re.compile(r'data:\[{id:(.*?),title:"'),response.text)[0])#找找视频链接
vod_name.append(re.findall(re.compile(r',title:"(.*?)",desc:"'),response.text)[0])#找找视频标题
for i in re.findall(re.compile(r'{sid:"(.*?)",key:'),response.text):
url ="https://web-api.rr.tv/web/drama/play?webChannel=M_STATION&dramaId="+vod_list[0]+"&episodeId="+i+"&2-7-17xx"#拼接地址
response = requests.get(url = url,headers = headers)
get_down_url.append(str(json.loads(response.text)['data']['url']))#拿下载直链进list
def down_begin(url,i):
print("开始多线程下载"+vod_name[0]+"第"+str(i)+"集")
r = requests.get(url = url,headers = headers)#下载请求
f = open("./"+vod_name[0]+"/第"+str(i)+"集.MP4", "wb")#保存视频
for chunk in r.iter_content(chunk_size=512):
if chunk:
f.write(chunk)
if __name__ == '__main__':
url='https://m.rr.tv/detail/xxxxx?snum=1&episode=1'#进入rr.tv自行获取
get_vod(url)
os.mkdir('./'+vod_name[0])#创建视频保存目录
with ThreadPoolExecutor(10) as f:#这里写多线程参数,适合几十集的电视剧使用
for i,url in enumerate(get_down_url):
i=int(i)+1
f.submit(down_begin,url = url,i=i)