python多线程与其他语言相比有很大的区别,python中的多线程,由于cil锁的缘故,导致cpu同一时间只能执行一个线程,这样产生的问题就是别管你的cpu是几核的,都没什么卵用。但是这种情况是计算密集性才会有的问题,如果牵涉到的是计算密集性,那么python可以通过多线程来做这种操作,这样就解决了多核缺并不能提高效率的问题。
今天要用的爬虫其实是cpu把任务分配给了其他硬件进行操作,cpu只牵涉到了分配,其他不用自己处理,这样即使是多线程,轮询分配下任务并不降低什么效率,同样类型的IO操作,我们都可以使用多线程。
import requests
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import time
all_urls = []
def get_url_list(target_url):
list_infos = []
# 访问目标地址
ret = requests.get(url=target_url)
soup = BeautifulSoup(ret.text, 'html.parser')
list_box = soup.find('div', attrs={
'class':'list'
})
lis = list_box.find_all('li')
for li in lis:
info = li.find('h3')
title = info.find('a').text
target = info.find('a').get('href')
list_infos.append({
'title' : title,
'target' : target
})
return list_infos
def run():
for item in range(1, 51):
all_urls.append(get_url_list('http://www.chinamedevice.cn/product/12/11/1127/%s.html'%item))
# 进程执行的任务返回的结果保存至url列表
def get_result(future):
all_urls.append(future.result())
def thred_run():
# 创建一个包含5条线程的线程池
with ThreadPoolExecutor(5) as pool:
for item in range(1, 51):
# 向线程池提交一个task, url会作为get_url_list()函数的参数
res = pool.submit(get_url_list, 'http://www.chinamedevice.cn/product/12/11/1127/%s.html' % item)
# 为res添加线程完成的回调函数
res.add_done_callback(get_result)
if __name__ == '__main__':
start = time.perf_counter()
thred_run()
# run()
end = time.perf_counter()
print(all_urls, len(all_urls), '总用时:%s' % (end - start))
单次测试,使用常规的单进程单线程爬取50页即1500条数据所耗费的时间大约在45秒左右;而我们使用单进程5线程获取同样的数据大概耗费了10秒左右,具体线程数根据自己需求
资源均来自第三方,谨慎下载,前往第三方网站下载