线程池概述_练习
相对于使用多线程,使用线程池的好处在于,避免了系统频繁的结束线程和开启线程带来的计算机系统性能的下降,从而专注于当前程序的性能。
线程池中的线程可以“不停”的去完成排队中的任务。
当然线程池中的线程也是不可以无限制开启的,开启线程池会占用大量的系统资源,过大线程池会导致整体的系统性能下降,进而会影响程序性能。
大量的IO操作,也是需要很高的系统性能来完成的。
正因如此,多线程和线程池,对于爬虫的性能增益不是很明显,通常这样方案的爬虫用在小型数据,网络速度较快的环境下。
即使在最为优越的环境下,多线程or
线程池也不能够在整个程序中使用,应当找出找出对应程序中最为阻塞的操作,将此操作归入线程池,以达到降低阻塞,提升性能的目的。
作为练习编写了这么一个小的程序用于理解 ( 练习案例,不喜勿喷 )
它是可以下载当前页面第一次加载出来的所有视频
#!/usr/bin/env python
# encoding: utf-8
"""
@file: 线程池爬取梨视频.py
@time: 2020/3/1 19:26
"""
import os
import requests
from lxml import etree
import re
from multiprocessing.dummy import Pool
headers = {
'Connection': 'close', # 请求成功释放当前资源
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/80.0.3987.116 Safari/537.36'
}
def files():
file = './梨视频'
if not os.path.exists(file):
os.mkdir(file)
return file
def page():
# 对url发起请求解析解析出视频的详情页的url和视频名称
url = 'https://www.pearvideo.com/category_5'
page_text = requests.get(url=url, headers=headers).text
tree = etree.HTML(page_text)
li_list = tree.xpath('//ul[@id="listvideoListUl"]/li | //ul[@id="categoryList"]/li')
urls = [] # 存储所有视频的连接和名字
for li in li_list:
detail_li = 'https://www.pearvideo.com/' + li.xpath('./div/a/@href')[0]
name = li.xpath('./div/a/div[2]/text()')[0] + '.mp4'
# 都详情页的url发请求
detail_page_text = requests.get(url=detail_li, headers=headers).text
# 从详情页中解析出视频的url
# var contId="1657067",liveStatusUrl="liveStatus.jsp",liveSta="",playSta="1",autoPlay=!1,isLiving=!1,
# isVrVideo=!1,hdflvUrl="",sdflvUrl="",hdUrl="",sdUrl="",ldUrl="",
# srcUrl="https://video.pearvideo.com/mp4/third/20200229/cont-1657067-11964200-120139-hd.mp4",
# vdoUrl=srcUrl,skinRes="//www.pearvideo.com/domain/skin",videoCDN="//video.pearvideo.com";
ex = 'srcUrl="(.*?)",vdoUrl'
video_url = re.findall(ex, detail_page_text)[0]
dic = {
'name': name,
'url': video_url
}
urls.append(dic)
return urls
def get_video_data(dic):
url = dic['url']
print(dic['name'], '正在下载。。。')
data = requests.get(url=url, headers=headers).content
# 持久化存储操作
file_dta = files() + '/' + dic['name']
with open(file_dta, 'wb') as fp:
fp.write(data)
print(dic['name'], '下载成功!!!')
def pools():
# 使用线程池对视频的数据进行请求(较为耗时的阻塞操作)
pool = Pool(4)
pool.map(get_video_data, page())
pool.close()
pool.join()
if __name__ == '__main__':
files()
pools()
page()
print('Over!!!')
不得擅用,更不得将此程序用于商业
爬虫虽好请勿滥用!!!