小白日常学习 视频异步爬取
import requests,re,os,timeimport asyncio
import aiofile
import aiohttp
"""
文件读取方式:
read():读取文件(读取size字节,默认读取全部)
readline():读取一行
readline() :读取缓冲buf(io.DEFAULT_SET_BUFFER),返回每一行所组成的列表
iter:使用迭代器遍历读取文件 f.open(name);iter_f = iter(f);用for line in iter_f循环迭代器
文件写入方式:
write(str):将字符串写入文件
writelines(sequence_of_strings):写多行到文件,参数为可迭代的对象
"""
headers= {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
}
url = "https://www.91kanju.com/vod-play/59611-1-1.html"
defget_m3u8(url):
resp = requests.get(url=url,headers=headers)
resp.encoding =resp.apparent_encoding
if resp.status_code == 200:
returnresp
else:
print("----没有响应----")
def m3u8_prase(m3u8_url):
m3u8 = get_m3u8(m3u8_url)
with open('../u8.m3u8', "w", encoding="utf-8") as f:
f.write(m3u8.text)
# 解析m3u8文件
dics = []
with open("../u8.m3u8", mode="r", encoding="utf-8") as f:
for n in f: #open读取出来的是列表
# 先去掉空白 换行之类
n = n.strip()
if n.startswith("#"):
continue
else:
name =n.split('/')[-1]
name = re.sub('png','ts',name)
print(name)
dic = {
"name": str(name),
"url": n
}
dics.append(dic)
return dics
async defmovie_down(dic,semaphore):
asyncwith semaphore:# 限制并发量
m_url = dic["url"]
name = dic["name"]
print("---------------异步协程开启----------------")
async withaiohttp.ClientSession() as session:
async with awaitsession.get(m_url) as mov:
path = 'mov/' + name
async with aiofile.async_open(path,'wb') as f_b:
mov = awaitmov.read()
await f_b.write(mov)
print(name,'下载完成')
awaitasyncio.sleep(1)
defmian():
semaphore = asyncio.Semaphore(20)# 限制并发量为20
start_time = time.time()
if not os.path.exists('mov'):
os.mkdir("mov")
resp = get_m3u8(url)
# print(resp.text)
m3u8_url = re.findall(r'line\ \+ "(.*?)"\);',resp.text)
print(m3u8_url)
dics = m3u8_prase(m3u8_url)
tasks = []
for dic in dics:
task = asyncio.ensure_future(movie_down(dic,semaphore))
tasks.append(task)
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
print('一共耗时',time.time()-start_time)
def he_bing():
pass
if __name__ == '__main__':
loop = asyncio.get_event_loop()
mian()
"""
假如你的并发达到2000个,程序会报错:ValueError: too many file descriptors in select()。报错的原因字面上看是 Python 调取的 select 对打开的文件有最大数量的限制,这个其实是操作系统的限制,linux打开文件的最大数默认是1024,windows默认是509,超过了这个值,程序就开始报错。这里我们有三种方法解决这个问题:
1.限制并发数量。(一次不要塞那么多任务,或者限制最大并发数量)
2.使用回调的方式。
3.修改操作系统打开文件数的最大限制,在系统里有个配置文件可以修改默认值,具体步骤不再说明了。
不修改系统默认配置的话,个人推荐限制并发数的方法,设置并发数为500,处理速度更快。
""" 一直想学习m3u8的下载方式 片段式下载,再拼接嘛? `main`吧,咋能是`mian` 爬多了怕不是会入yu{:1_886:} 学习一下
页:
[1]