这篇文章主要介绍“Python爬虫中怎么使用线程池”,在日常操作中,相信很多人在Python爬虫中怎么使用线程池问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python爬虫中怎么使用线程池”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
学到现在,我们可以说已经学习了爬虫的基础知识,如果没有那些奇奇怪怪的反爬虫机制,基本上只要有时间分析,一般的数据都是可以爬取的,那么到了这个时候我们需要考虑的就是爬取的效率了,关于提高爬虫效率,也就是实现异步爬虫,我们可以考虑以下两种方式:一是线程池的使用(也就是实现单进程下的多线程),一是协程的使用(如果没有记错,我所使用的协程模块是从python3.4以后引入的,我写博客时使用的python版本是3.9)。
今天我们先来讲讲线程池。
我们先用普通的同步的形式写一段代码
import time def func(url): print("正在下载:", url) time.sleep(2) print("下载完成:", url) if __name__ == '__main__': start = time.time() # 开始时间 url_list = [ "a", "b", "c" ] for url in url_list: func(url) end = time.time() # 结束时间 print(end - start)
不出所料。运行时间果然是六秒
那么如果我们使用线程池运行上述代码又会怎样呢?
import time from multiprocessing import Pool def func(url): print("正在下载:", url) time.sleep(2) print("下载完成:", url) if __name__ == '__main__': start = time.time() # 开始时间 url_list = [ "a", "b", "c" ] pool = Pool(len(url_list)) # 实例化一个线程池对象,并且设定线程池的上限数量为列表长度。不设置上限也可以。 pool.map(func, url_list) end = time.time() # 结束时间 print(end - start)
我们发现这次我们的运行时间只用2~3秒。其实我们可以将线程池简单的理解为将多个任务同时进行。
注意:
1.我使用的是 pycharm,如果使用的是 VS 或者说是 python 自带的 idle,在运行时我们只能看到最后时间的输出。
2.我们输出结果可能并不是按 abc 的顺序输出的。
因为我们的重点是线程池的爬取效率提高,我们就简单的爬取一页的图片。
import requests import time import os from lxml import etree def save_photo(url, title): # UA伪装 header = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36" } # 发送请求 photo = requests.get(url=url, headers=header).content # 创建路径,避免重复下载 if not os.path.exists("C:\Users\ASUS\Desktop\CSDN\高性能异步爬虫\线程池\同步爬虫爬取4K美女图片\" + title + ".jpg"): with open("C:\Users\ASUS\Desktop\CSDN\高性能异步爬虫\线程池\同步爬虫爬取4K美女图片\" + title + ".jpg", "wb") as fp: print(title, "开始下载!!!") fp.write(photo) print(title, "下载完成!!!") if __name__ == '__main__': start = time.time() # 创建文件夹 if not os.path.exists("C:\Users\ASUS\Desktop\CSDN\高性能异步爬虫\线程池\同步爬虫爬取4K美女图片"): os.mkdir("C:\Users\ASUS\Desktop\CSDN\高性能异步爬虫\线程池\同步爬虫爬取4K美女图片") # UA伪装 header = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36" } # 指定url url = "https://pic.netbian.com/4kmeinv/" # 发送请求,获取源码 page = requests.get(url = url, headers = header).text # xpath 解析,获取图片的下载地址的列表 tree = etree.HTML(page) url_list = tree.xpath('//*[@id="main"]/div[3]/ul/li/a/@href') # 通过下载地址获取高清图片的地址和图片名称 for href in url_list: new_url = "https://pic.netbian.com" + href # 再一次发送请求 page = requests.get(url = new_url, headers = header).text # 再一次 xpath 解析 new_tree = etree.HTML(page) src = "https://pic.netbian.com" + new_tree.xpath('//*[@id="img"]/img/@src')[0] title = new_tree.xpath('//*[@id="img"]/img/@title')[0].split(" ")[0] # 编译文字 title = title.encode("iso-8859-1").decode("gbk") # 下载,保存 save_photo(src, title) end = time.time() print(end - start)
让我们看看同步爬虫需要多长时间
然后再让我们看看使用线程池的异步爬虫爬取这些图片需要多久
import requests import time import os from lxml import etree from multiprocessing import Pool def save_photo(src_title): # UA伪装 header = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36" } # 发送请求 url = src_title[0] title = src_title[1] photo = requests.get(url=url, headers=header).content # 创建路径,避免重复下载 if not os.path.exists("C:\Users\ASUS\Desktop\CSDN\高性能异步爬虫\线程池\异步爬虫爬取4K美女图片\" + title + ".jpg"): with open("C:\Users\ASUS\Desktop\CSDN\高性能异步爬虫\线程池\异步爬虫爬取4K美女图片\" + title + ".jpg", "wb") as fp: print(title, "开始下载!!!") fp.write(photo) print(title, "下载完成!!!") if __name__ == '__main__': start = time.time() # 创建文件夹 if not os.path.exists("C:\Users\ASUS\Desktop\CSDN\高性能异步爬虫\线程池\异步爬虫爬取4K美女图片"): os.mkdir("C:\Users\ASUS\Desktop\CSDN\高性能异步爬虫\线程池\异步爬虫爬取4K美女图片") # UA伪装 header = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36" } # 指定url url = "https://pic.netbian.com/4kmeinv/" # 发送请求,获取源码 page = requests.get(url = url, headers = header).text # xpath 解析,获取图片的下载地址的列表 tree = etree.HTML(page) url_list = tree.xpath('//*[@id="main"]/div[3]/ul/li/a/@href') # 存储最后的网址和标题的列表 src_list = [] title_list = [] # 通过下载地址获取高清图片的地址和图片名称 for href in url_list: new_url = "https://pic.netbian.com" + href # 再一次发送请求 page = requests.get(url = new_url, headers = header).text # 再一次 xpath 解析 new_tree = etree.HTML(page) src = "https://pic.netbian.com" + new_tree.xpath('//*[@id="img"]/img/@src')[0] src_list.append(src) title = new_tree.xpath('//*[@id="img"]/img/@title')[0].split(" ")[0] # 编译文字 title = title.encode("iso-8859-1").decode("gbk") title_list.append(title) # 下载,保存。使用线程池 pool = Pool() src_title = zip(src_list, title_list) pool.map(save_photo, list(src_title)) end = time.time() print(end - start)
到此,关于“Python爬虫中怎么使用线程池”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。