最近在研究如何利用python爬取某91网站的视频资源,有一点小小的成果,由于考虑到一些其他因素,此处只提供获取视频的方法!!!好了,言归正传,进入主题。
首先,我们需要有一个构建代码的思路,或者说是爬取的流程
一、流程:
1.请求548121-1-1.html的页面代码
2.从源代码中提取m3u8
3.下载m3u8
4.读取m3u8文件,下载视频,(注意反扒问题) 超级播
import ...
def n_path():
pass
if __name__ == '__main__':
pass
二、现在我们就要构建我们的代码
1.书写主模块,将一些必要的变量和全局操作放在该部分!
注意:moive文件夹建议手动创建成exclused形式的文件夹,要不卡死了别找我!!!
if __name__ == '__main__':
start = time.time()
failure_list = [] # 保存下载失败的片段
# 创建一个文件夹
list = ['./moive', './mp4'] # 建议手动创建成exclused形式的文件夹
for path in list:
if not os.path.exists(path):
os.mkdir(path)
else:
print('文件夹已存在!!!')
headers = {
'Connection': 'close',
"user-agent": "*****"
}
for page in range(1, 29):
url = "*****" + str(page) + ".html" # 直接拼接出所用网址
# 代理已过期,再次使用时使用新代理,代理最好在下载视频时使用,此处没用到
proxies = ['', '']
proxy = {'HTTPS': random.choice(proxies)} # 使每集的代理不一样
print(proxy)
# "copy/b moive\*.ts mp4\movie.mp4"
moive_name = "欧美电视剧第%d集" % page
address = f"copy/b moive\*.ts mp4\{moive_name}"
main(url)
print(("欧美电视剧第%d集下载完毕!!!" % page) + url)
os.rmdir('./moive') # 此时该文件夹应该为空,回收文件夹moive
end = time.time()
print('总耗时', end - start)
print('程序结束!!!')
2.需要用到的包
import requests
import re
import asyncio
import aiohttp
import aiofiles
import os
import glob
import random
import time
3.建立模块
3.1获取m3u8_url
def get_m3u8_url(url, headers):
obj = re.compile(r"url: '(?P
response = requests.get(url=url, headers=headers)
m3u8_url = obj.search(response.text).group("url")
print(m3u8_url)
print("m3u8_url 下载完毕!")
return m3u8_url
3.2下载 m3u8_file
def download_m3u8_file(url, name):
# 下载m3u8文件
response = requests.get(url=url, headers=headers, timeout=30, proxys=proxy)
with open(name, mode="wb") as f:
f.write(response.content)
response.close()
print("下载 “moive.m3u8 完毕!")
# 加载太慢直接写进文件
3.3 下载ts,由于使用的是异步协程爬取信息,此处对网络超时、请求错误等进行处理。
async def download_ts(url, name, session, flag=0):
try:
async with session.get(url) as response:
async with aiofiles.open(f"moive/{name}", mode="wb") as fp:
# 双await是由于下载和读写均异步
await fp.write(await response.content.read()) # 把下载的内容写入到文件内
if flag == 1:
data_list = []
data_list.append(name)
data_list.append(url)
failure_list.remove(data_list)
data_list.clear() # 每次都清空,但其实每判断一次都会自动清零,但不想修改运行后的代码
except:
print('请求失败!')
data = []
if name not in data:
data.append(name)
data.append(url)
if data not in failure_list:
failure_list.append(data)
print(f"{name}下载完毕")
3.4 由于下载ts前需要先对m3u8文件将进行处理,且此处对反扒问题进行处理,如果不对302自动重新请求处理,虽然可以下载到视频,但是有少数ts文件会无法下载下来。可以试想一下,看到关键是否卡住是多气人,或者直接跳过精彩片段。
async def aio_download():
n = 0
tasks = [] # 创建任务列表
# 在这创建session,避免多次创建
async with aiohttp.ClientSession() as session:
async with aiofiles.open("movie_m3u8.txt", mode="r", encoding='utf-8') as fp:
async for line in fp:
if line.startswith("#"): # 跳过#号语句
continue
line = line.strip()
if len(line) != 0: # 对302情况进行处理,情况不一样,该平台不同源的影片处理方式不一样
async with session.get(url=line, headers=headers, allow_redirects=False) as response:
result = response.text
print(str(result))
obj = re.compile(r"'Location': '(?P
new_requests_url = obj.search(str(result)).group("url")
print(new_requests_url)
n += 1
k = "{:0>4d}".format(n)
task = asyncio.create_task(download_ts(new_requests_url, k + ".ts", session, 0)) # 创建任务
tasks.append(task)
await asyncio.wait(tasks) # 等待任务结束
3.4.1 效果图
3.5 由于在构建代码是没有考虑到超时问题,后面构建的是否又不想重现写,突发奇想CV大法构建一个新的模块,真的是机智如我。
async def reaio_download(): # 直接新建一个模块调用download_ts
tasks = [] # 创建任务列表
# 在这创建session,避免多次创建
async with aiohttp.ClientSession() as session:
for recall in failure_list:
if len(recall[1]) == 0:
failure_list.remove(recall)
continue
task = asyncio.create_task(download_ts(recall[1], recall[0], session, 1)) # 创建任务
tasks.append(task)
await asyncio.wait(tasks) # 等待任务结束
3.6 接下来就是合并文件了,merge_ts
def merge_ts():
path = './moive'
files = os.listdir(path)
moive_name = "反贪风暴第%d集" % page
address = f"copy/b moive\*.ts mp4\{moive_name}"
print(address)
if len(files) != 0:
# "copy/b moive\*.ts mp4\movie.mp4",安卓系统下的命令,苹果系统无法使用
os.system(address) # 这里的文件名需要需改,否则会覆盖前一集
print(moive_name + "合并完成!")
else:
print(moive_name + "合并失败,文件夹为空文件夹!!!")
3.7 做为一个懒人是不可能自己动手取删除ts等文件的啦!给它写个代码
def deleteFile(file_path):
print("开始删除文件")
for infile in glob.glob(os.path.join(file_path, '*.ts')):
os.remove(infile)
paths = ["movie_m3u8.txt"] # 文件路径
for path in paths:
if os.path.exists(path): # 如果文件存在
# 删除文件
os.remove(path)
else:
print('no such file!!!') # 则返回文件不存在
print("文件删除完成")
3.8 写了这么多模块,肯定要组装起来呀!
def main(url):
# 1.获取m3u8的地址
m3u8_url = get_m3u8_url(url, headers)
# 2.下载m3u8文件
download_m3u8_file(m3u8_url, "movie_m3u8.txt")
# 3. 下载视频
# 异步协程
# loop = asyncio.get_event_loop()
# loop.run_until_complete(aio_download())
asyncio.run(aio_download())
# 4. 合并ts文件
merge_ts()
# 5.删除ts文件
file_path = './moive'
deleteFile(file_path)
4 搞了这么多嘻嘻哈哈的操作,不给个整体肯定是在欺负人!!!
#!/usr/bin/env python
# author = 'MIMG LOU'
# time = 2021/9/29
# project = 扒光一部电视剧
'''
流程:
1.请求548121-1-1.html的页面代码
2.从源代码中提取m3u8
3.下载m3u8
4.读取m3u8文件,下载视频,超级播
'''
# 编程思想:各需求分为各个模块,通过主模块调用,主函数尽量只防止全局参数和只需创建一次的内容
import requests
import re
import asyncio
import aiohttp
import aiofiles
import os
import glob
import random
import time
def get_m3u8_url(url, headers):
obj = re.compile(r"url: '(?P
response = requests.get(url=url, headers=headers)
m3u8_url = obj.search(response.text).group("url")
print(m3u8_url)
print("m3u8_url 下载完毕!")
return m3u8_url
def download_m3u8_file(url, name):
# 下载m3u8文件
response = requests.get(url=url, headers=headers, timeout=30, proxys=proxy)
with open(name, mode="wb") as f:
f.write(response.content)
response.close()
print("下载 “moive.m3u8 完毕!")
# 加载太慢直接写进文件
async def download_ts(url, name, session, flag=0):
try:
async with session.get(url) as response:
async with aiofiles.open(f"moive/{name}", mode="wb") as fp:
# 双await是由于下载和读写均异步
await fp.write(await response.content.read()) # 把下载的内容写入到文件内
if flag == 1:
data_list = []
data_list.append(name)
data_list.append(url)
failure_list.remove(data_list)
data_list.clear() # 每次都清空,但其实每判断一次都会自动清零,但不想修改运行后的代码
except:
print('请求失败!')
data = []
if name not in data:
data.append(name)
data.append(url)
if data not in failure_list:
failure_list.append(data)
print(f"{name}下载完毕")
async def aio_download():
n = 0
tasks = [] # 创建任务列表
# 在这创建session,避免多次创建
async with aiohttp.ClientSession() as session:
async with aiofiles.open("movie_m3u8.txt", mode="r", encoding='utf-8') as fp:
async for line in fp:
if line.startswith("#"): # 跳过#号语句
continue
line = line.strip()
if len(line) != 0: # 对302情况进行处理,情况不一样,该平台不同源的影片处理方式不一样
async with session.get(url=line, headers=headers, allow_redirects=False) as response:
result = response.text
print(str(result))
obj = re.compile(r"'Location': '(?P
new_requests_url = obj.search(str(result)).group("url")
print(new_requests_url)
n += 1
k = "{:0>4d}".format(n)
task = asyncio.create_task(download_ts(new_requests_url, k + ".ts", session, 0)) # 创建任务
tasks.append(task)
await asyncio.wait(tasks) # 等待任务结束
async def reaio_download(): # 直接新建一个模块调用download_ts
tasks = [] # 创建任务列表
# 在这创建session,避免多次创建
async with aiohttp.ClientSession() as session:
for recall in failure_list:
if len(recall[1]) == 0:
failure_list.remove(recall)
continue
task = asyncio.create_task(download_ts(recall[1], recall[0], session, 1)) # 创建任务
tasks.append(task)
await asyncio.wait(tasks) # 等待任务结束
def merge_ts():
path = './moive'
files = os.listdir(path)
moive_name = "欧美电视剧第%d集" % page
address = f"copy/b moive\*.ts mp4\{moive_name}"
print(address)
if len(files) != 0:
# "copy/b moive\*.ts mp4\movie.mp4",安卓系统下的命令,苹果系统无法使用
os.system(address) # 这里的文件名需要需改,否则会覆盖前一集
print(moive_name + "合并完成!")
else:
print(moive_name + "合并失败,文件夹为空文件夹!!!")
'''
删除合并后的文件
file_path
'''
def deleteFile(file_path):
print("开始删除文件")
for infile in glob.glob(os.path.join(file_path, '*.ts')):
os.remove(infile)
paths = ["movie_m3u8.txt"] # 文件路径
for path in paths:
if os.path.exists(path): # 如果文件存在
# 删除文件
os.remove(path)
else:
print('no such file!!!') # 则返回文件不存在
print("文件删除完成")
def main(url):
# 1.获取m3u8的地址
m3u8_url = get_m3u8_url(url, headers)
# 2.下载m3u8文件
download_m3u8_file(m3u8_url, "movie_m3u8.txt")
# 3. 下载视频
# 异步协程
# loop = asyncio.get_event_loop()
# loop.run_until_complete(aio_download())
asyncio.run(aio_download())
# 4. 合并ts文件
merge_ts()
# 5.删除ts文件
file_path = './moive'
deleteFile(file_path)
if __name__ == '__main__':
start = time.time()
failure_list = [] # 保存下载失败的片段
# 创建一个文件夹
list = ['./moive', './mp4'] # 建议手动创建成exclused形式的文件夹
for path in list:
if not os.path.exists(path):
os.mkdir(path)
else:
print('文件夹已存在!!!')
headers = {
'Connection': 'close',
"user-agent": "***"
}
for page in range(1, 29):
url = "***" + str(page) + ".html" # 直接拼接出所用网址
# 代理已过期,再次使用时使用新代理,代理最好在下载视频时使用,此处没用到
proxies = ['','']
proxy = {'HTTPS': random.choice(proxies)} # 使每集的代理不一样
print(proxy)
# "copy/b moive\*.ts mp4\movie.mp4"
moive_name = "反贪风暴第%d集" % page
address = f"copy/b moive\*.ts mp4\{moive_name}"
main(url)
print(("反贪风暴第%d集下载完毕!!!" % page) + url)
os.rmdir('./moive') # 此时该文件夹应该为空,回收文件夹moive
end = time.time()
print('总耗时', end - start)
print('程序结束!!!')
'''
最终电视剧的聚集存放在MP4文件中
'''
5 来看一下效果吧!!!
白嫖生活从此开始!!!