python scrapy框架基如何实现多线程_Python多线程爬图Scrapy框架爬图
一、背景
对于日常Python爬虫由于效率问题,本次测试使用多线程和Scrapy框架来实现抓取
进程:
优点:充分利用多核CPU(能够同时进行多个操作)
缺点:系统资源消耗大,重新开辟内存空间
线程:
优点:共享内存,IO操作可以创造出并发操作
缺点:抢占资源,请求上下文切换消耗时间
但是对于python这种解释性语言带有GIL(全局解释器锁)解释器锁,同一时刻只能有一个线程在运行,遇到IO操作才会释放切换。感觉没必要多线程,但是经测试,多线程还是在很大程度能够提升效率。
二、代码
2.1 多线程爬图
定义了10个线程去爬去每个页面的具体表情的url存放在类中的img_url_list内,然后通过10个线程从这个列表内取url进行本地图片下载。
核心代码
#定义全局页面url列表
page_url_list =[]#定义具体各表情图片url列表
img_url_list =[]#定义rlock进程锁
rlock =threading.RLock()def __init__(self,page_number=10,img_dir='imgdir',thread_number=5):""":param page_number: 抓去多少个页面,默认10
:param img_dir: 定义图片目录
:param thread_number:默认5个线程"""self.spider_url= 'https://www.doutula.com/photo/list/?page='self.page_number=int(page_number)
self.img_dir=img_dir
self.thread_num=thread_numberdef __add_urllist(self):"""定义从page_url_list 爬取具体的image的url
:return:"""
whileTrue:
DutuSpider.rlock.acquire()if len(DutuSpider.page_url_list) ==0:
DutuSpider.rlock.release()break
else:
page_url=DutuSpider.page_url_list.pop()
DutuSpider.rlock.release()
response= requests.get(page_url, headers=self.__set_header())
soup= BeautifulSoup(response.content,'lxml')
sou_list= soup.find_all('img',attrs={'class':'img-responsive lazy image_dta'})#将获取到的具体表情图标的url保存添加进img_url_list 列表
for url_content insou_list:
DutuSpider.rlock.acquire()
DutuSpider.img_url_list.append(url_content['data-original'])
DutuSpider.rlock.release()def __download_img(self):"""从image_url_list中来下载image到本地
:return:"""
whileTrue:
DutuSpider.rlock.acquire()if len(DutuSpider.img_url_list) ==0:
DutuSpider.rlock.release()continue
else:
img_url=DutuSpider.img_url_list.pop()
DutuSpider.rlock.release()try:#图片名称
img_name = img_url.split('/')[-1]#下载图片
urllib.urlretrieve(img_url,os.path.join(self.img_dir,img_name))print('donload img %s' %img_name)exceptException as e:pass
defrun(self):#启动thread_num个进程来爬去具体的img url 链接
for th inrange(self.thread_num):
add_pic_t= threading.Thread(target=self.__add_urllist)
add_pic_t.start()#启动thread_num个来下载图片
for img_th inrange(self.thread_num):
download_t= threading.Thread(target=self.__download_img)
download_t.start()
2.2 Scrapy框架爬图
利用Scrapy框架来爬取表情,items定义图片名称和每个图片的url,scrapy主文件来爬取每个图片的url来返回,piplines来进行本地文件存储。
核心代码
#items,定义img的url和name
classScrapyDoutulaiItem(scrapy.Item):#define the fields for your item here like:
#name = scrapy.Field()
#定义图片url和name
img_url =scrapy.Field()
img_name=scrapy.Field()#爬虫文件
classDoutulaiSpiderSpider(scrapy.Spider):
name= 'doutulai_spider'allowed_domains= ['www.doutula.com']
start_urls= ['https://www.doutula.com/photo/list/']
page= 1
defparse(self, response):
content_items=ScrapyDoutulaiItem()#解析img_url列表,拿到图片的url和,图片名称
img_url_list = response.xpath('//img[@class="img-responsive lazy image_dta"]')#page_number = response.xpath('//*[@id="pic-detail"]/div/div[3]/div[3]/ul/li[12]/a/text()').extract_first()
page_number = response.xpath('//a[@class="page-link"][last()]/text()').extract_first()for img_content inimg_url_list:
content_items['img_url'] = img_content.xpath('./@data-original').extract_first()
content_items['img_name'] = img_content.xpath('./@data-original').extract_first().split('/')[-1]print(content_items)yieldcontent_items#不断爬取新页面
if self.page <=page_number:
self.page+= 1next_url= self.start_urls[0] + '?page=' +str(self.page)yieldscrapy.Request(next_url)#pipeline下载图片
from urllib importurlretrievefrom scrapy_doutulai.settings importDOWNLOAD_DIRclassScrapyDoutulaiPipeline(object):def __init__(self):"""判断下载目录是否存在"""
if notos.path.exists(DOWNLOAD_DIR):
os.makedirs(DOWNLOAD_DIR)defprocess_item(self, item, spider):"""下载图片
:param item:
:param spider:
:return:"""
try:
filename= os.path.join(DOWNLOAD_DIR,item['img_name'])print(filename)
urlretrieve(item['img_url'],filename)exceptException as e:pass
三、测试
测试使用2C2G centos7.4,python2.7版本,启动线程10个,爬去1000页的表情信息
3.1 多线程测试
启动爬虫
nohup doutulai/multithreading_spider/dutulai_spider.py &
查看系统负载
查看文件信息
3.2 Scrapy框架爬图
启动爬虫
nohup doutulai/scrapy_doutulai/scrapy_doutulai/main.py &
查看系统负载
查看文件信息
爬取的图片
3.3 持久化存储在OSS上
最终配合阿里云OSS的API来将图片持久化存储在对象存储内。
整体image下载地址:图片压缩包
四、总结
经测试自己写的多线程爬图,CPU使用率很高,磁盘IO很大。Scrapy默认也是10个线程,但由于自己有磁盘IO操作,CPU使用平稳。
虽然Python有GIL,但是在适当的场景下利用其多线程会很大程度的提升效率。之前如果单线程10分钟,利用多线程可以缩短3/2的 时间,具体需要结合线程数,磁盘与网络IO来判断。
最后说一件重要的事,只怕有同学错过。云计算现在白菜价了,2018年各大云计算厂商竞相降价,云服务器低至300元/年。现在不管是学习linux系统,运行长时间工作的爬虫,上线个人App或小程序,搭建网站做个人站长,都是时候上云服务了,错过这一波可能你就掉队。这里整理了一份云计算优惠活动产品列表,点击拿走不谢!
本文转自:http://blog.51cto.com/kaliarch/2162411
python scrapy框架基如何实现多线程_Python多线程爬图Scrapy框架爬图相关推荐
- python 选择题 多线程_python多线程练习题
python多线程练习题 多线程练习题目,涉及知识点较多,属于很好的练习题. 题目要求 通过多线程实现类似linux中的>>功能,也就是将日志记录到指定的文件中. 题目分析 基本为main ...
- python如何使用多线程_python多线程与线程
进程与线程的概念 进程 考虑一个场景:浏览器,网易云音乐以及notepad++ 三个软件只能顺序执行是怎样一种场景呢?另外,假如有两个程序A和B,程序A在执行到一半的过程中,需要读取大量的数据输入(I ...
- python 选择题 多线程_python多线程一些知识点梳理
学习python的进程和线程以来,对这两个概念一直都处于模糊状态,所以决定花点时间好好学习一下这块知识.以下是我自己在学习过程中形成的一些疑问以及搜集的一些相应的比较好的答案,整理如下,方便复习自查. ...
- python守护多线程_Python多线程Threading、子线程与守护线程实例详解
线程Threading: python中多线程需要使用threading模块 线程的创建与运行: 1.直接调用threading的Thread类: 线程的创建:线程对象=thread.Thread(t ...
- python 接口测试多线程_python多线程测试接口性能,就是这么简单
除了使用性能测试工具进行性能测试,我们也可以直接用python多线程进行性能测试. 下面,使用这几个模块,对一个查询接口做性能测试: requests:发送http请求 json:返回的字符串转换成j ...
- python如何使用多线程_python多线程应用中的详细介绍
python多线程在应用的时候有不少的事情需要重点的注意.其实只要掌握这些相关的技术段就能保证这个应用的完整.下面我们来看看具体是需要如何进行操作. 今天看了近一天关于多线程的应用中,如何安全调用py ...
- python多线程_python多线程:控制线程数量
背景 前段时间学习了python的多线程爬虫,当时爬取一个图片网站,开启多线程后,并没有限制线程的数量,也就是说,如果下载1000张图片,会一次性开启1000个子线程同时进行下载 现在希望控制线程数量 ...
- python如何使用多线程_Python多线程与多线程中join()的用法
Python多线程与多进程中join()方法的效果是相同的. 下面仅以多线程为例: 首先需要明确几个概念: 知识点一: 当一个进程启动之后,会默认产生一个主线程,因为线程是程序执行流的最小单元,当设置 ...
- python多线程_Python多线程和队列结合demo
每周一07:22,准时为你充电 一.使用场景 大家都知道python的多线程不是真正的多线程,但是对于io类型的任务,多线程还是能发挥作用的.那么多个线程之间是如何进行变量共享的呢,很多时候我们可以借 ...
最新文章
- wds和dhcp分开做需要注意问题
- opencv dnn完整示例
- android 上拉隐藏布局,Recycleview上拉隐藏与下拉显示
- Engagement Center launchpad点了Tile后的处理机制
- 多功能嵌入式解码软件(2)
- tensorflow框架
- SQLServer中的死锁的介绍
- HDU 2242 考研路茫茫——空调教室
- Centos 安装配置gerrit
- 如何在 Mac 上使用“接力”回到上次离开的地方?
- c语言程序设计 姜书浩,Access 数据库实践教程
- Ubuntu16.04安装slickedit-pro2017
- js工厂模式和单例模式
- 全球与中国乳制品替代杏仁制品市场深度研究分析报告
- cortex-a9 架构概览
- 大数据学习的第一课-大数据概论和技术原理
- 衡水二中高考2021成绩查询,衡水二中高考(衡水二中2020清北录取)
- 小码农的职场人生一:由张小平离职引发的一些吐槽
- 如何管教患有拖延症的娃
- 优化企业会议解决方案
热门文章
- bat文件备份MySQL数据库
- linux英文包安装教程视频,Linux源码包安装过程讲解
- Java中proc是什么意思,Java PatientProcedureVo.setSignifProc方法代码示例
- java 序列化快捷键_IntelliJ IDEA生成 Serializable序列化UID的快捷键
- python流处理框架_Python操作分布式流处理系统Kafka
- Swagger注解-@ApiImplicitParams 和 @ApiImplicitParam
- python之循环(增删)内使用list.remove()
- 搭建空的maven多模块项目架构并且上传到远程git仓库(超详细 cmd命令版本)
- 初识Scrapy,在充满爬虫的世界里做一个好公民
- Spring Cloud with Turbine