失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > python scrapy框架基如何实现多线程_Python多线程爬图Scrapy框架爬图

python scrapy框架基如何实现多线程_Python多线程爬图Scrapy框架爬图

时间:2018-12-11 14:29:35

相关推荐

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= '/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= ['']

start_urls= ['/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来判断。

最后说一件重要的事,只怕有同学错过。云计算现在白菜价了,各大云计算厂商竞相降价,云服务器低至300元/年。现在不管是学习linux系统,运行长时间工作的爬虫,上线个人App或小程序,搭建网站做个人站长,都是时候上云服务了,错过这一波可能你就掉队。这里整理了一份云计算优惠活动产品列表,点击拿走不谢!

本文转自:/kaliarch/2162411

如果觉得《python scrapy框架基如何实现多线程_Python多线程爬图Scrapy框架爬图》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。