Python多線程爬圖&Scrapy框架爬圖

      網友投稿 830 2025-03-31

      一、背景


      Python多線程爬圖&Scrapy框架爬圖

      對于日常Python爬蟲由于效率問題,本次測試使用多線程和Scrapy框架來實現抓取**斗圖啦**表情。

      由于IO操作不使用CPU,對于IO密集(磁盤IO/網絡IO/人機交互IO)型適合用多線程,對于計算密集型:建議用多進程。

      進程:

      優點:充分利用多核CPU(能夠同時進行多個操作)

      缺點:系統資源消耗大,重新開辟內存空間

      線程:

      優點:共享內存,IO操作可以創造出并發操作

      缺點:搶占資源,請求上下文切換消耗時間

      但是對于python這種解釋性語言帶有GIL(全局解釋器鎖)解釋器鎖,同一時刻只能有一個線程在運行,遇到IO操作才會釋放切換。感覺沒必要多線程,但是經測試,多線程還是在很大程度能夠提升效率。

      二、代碼

      git地址

      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_number def __add_urllist(self): """ 定義從page_url_list 爬取具體的image的url :return: """ while True: 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 in sou_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: """ while True: 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) except Exception as e: pass def run(self): # 啟動thread_num個進程來爬去具體的img url 鏈接 for th in range(self.thread_num): add_pic_t = threading.Thread(target=self.__add_urllist) add_pic_t.start() # 啟動thread_num個來下載圖片 for img_th in range(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 class ScrapyDoutulaiItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() # 定義圖片url和name img_url = scrapy.Field() img_name = scrapy.Field() # 爬蟲文件 class DoutulaiSpiderSpider(scrapy.Spider): name = 'doutulai_spider' allowed_domains = ['www.doutula.com'] start_urls = ['https://www.doutula.com/photo/list/'] page = 1 def parse(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 in img_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) yield content_items # 不斷爬取新頁面 if self.page <= page_number: self.page += 1 next_url = self.start_urls[0] + '?page=' + str(self.page) yield scrapy.Request(next_url) #pipeline下載圖片 from urllib import urlretrieve from scrapy_doutulai.settings import DOWNLOAD_DIR class ScrapyDoutulaiPipeline(object): def __init__(self): """ 判斷下載目錄是否存在 """ if not os.path.exists(DOWNLOAD_DIR): os.makedirs(DOWNLOAD_DIR) def process_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) except Exception 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來判斷。

      Python Scrapy 任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:excel中的left函數怎么使用呢?
      下一篇:Nav2極簡筆記01-安裝與試用
      相關文章
      日韩精品一区二区亚洲AV观看| 成人亚洲性情网站WWW在线观看| 亚洲AV乱码一区二区三区林ゆな| 久久久久亚洲精品无码网址| 亚洲av中文无码| 亚洲国产精品无码久久98| 亚洲 暴爽 AV人人爽日日碰| 99999久久久久久亚洲| 亚洲色欲色欲www| va天堂va亚洲va影视中文字幕| 亚洲av永久无码精品三区在线4| 亚洲人成高清在线播放| 亚洲人成网站在线观看播放青青| 亚洲一本之道高清乱码| 亚洲一级大黄大色毛片| 国产成人亚洲综合一区| 亚洲人成网站18禁止| 噜噜噜亚洲色成人网站| 亚洲毛片不卡av在线播放一区| 亚洲午夜国产片在线观看| 亚洲中文字幕无码一区| 国产亚洲婷婷香蕉久久精品| 久久久久久a亚洲欧洲aⅴ| 亚洲av无码片在线播放| 亚洲最大福利视频网站| 亚洲第一成年网站大全亚洲| 亚洲中文无码av永久| 亚洲精品天堂无码中文字幕| 国产成人久久精品亚洲小说| 亚洲区小说区图片区| 国产亚洲婷婷香蕉久久精品| 在线观看亚洲人成网站| 亚洲一区精品视频在线| 亚洲国产精品网站在线播放| 国产亚洲精品美女| 亚洲精品无码久久久久| 亚洲午夜免费视频| 国产成人精品日本亚洲专一区 | 亚洲国产成人久久精品软件| 国产亚洲精品国产福利在线观看| 中文字幕亚洲专区|