Scrapy爬虫:抓取大量斗图网站最新表情图片
一:目標
第一次使用Scrapy框架遇到很多坑,堅持去搜索,修改代碼就可以解決問題。這次爬取的是一個斗圖網(wǎng)站的最新表情圖片www.doutula.com/photo/list,練習(xí)使用Scrapy框架并且使用的隨機user agent防止被ban,斗圖表情包每日更新,一共可以抓取5萬張左右的表情到硬盤中。為了節(jié)省時間我就抓取了1萬多張。
二:Scrapy簡介
Scrapy是一個為了爬取網(wǎng)站數(shù)據(jù),提取結(jié)構(gòu)性數(shù)據(jù)而編寫的應(yīng)用框架。 可以應(yīng)用在包括數(shù)據(jù)挖掘,信息處理或存儲歷史數(shù)據(jù)等一系列的程序中。
使用過程
- 創(chuàng)建一個Scrapy項目
- 定義提取的Item
- 編寫爬取網(wǎng)站的?spider?并提取?Item
- 編寫?Item Pipeline?來存儲提取到的Item(即數(shù)據(jù))
接下來的圖表展現(xiàn)了Scrapy的架構(gòu),包括組件及在系統(tǒng)中發(fā)生的數(shù)據(jù)流的概覽(綠色箭頭所示)。 下面對每個組件都做了簡單介紹,并給出了詳細內(nèi)容的鏈接。數(shù)據(jù)流如下所描述
Paste_Image.png
組件
-
Scrapy Engine
引擎負責控制數(shù)據(jù)流在系統(tǒng)中所有組件中流動,并在相應(yīng)動作發(fā)生時觸發(fā)事件。 詳細內(nèi)容查看下面的數(shù)據(jù)流(Data Flow)部分。 -
調(diào)度器(Scheduler)
調(diào)度器從引擎接受request并將他們?nèi)腙?#xff0c;以便之后引擎請求他們時提供給引擎。 -
下載器(Downloader)
下載器負責獲取頁面數(shù)據(jù)并提供給引擎,而后提供給spider。 -
Spiders
Spider是Scrapy用戶編寫用于分析response并提取item(即獲取到的item)或額外跟進的URL的類。 每個spider負責處理一個特定(或一些)網(wǎng)站。 更多內(nèi)容請看?Spiders?。 -
Item Pipeline
Item Pipeline負責處理被spider提取出來的item。典型的處理有清理、 驗證及持久化(例如存取到數(shù)據(jù)庫中)。 更多內(nèi)容查看?Item Pipeline?。 -
下載器中間件(Downloader middlewares)
下載器中間件是在引擎及下載器之間的特定鉤子(specific hook),處理Downloader傳遞給引擎的response。 其提供了一個簡便的機制,通過插入自定義代碼來擴展Scrapy功能。更多內(nèi)容請看?下載器中間件(Downloader Middleware)?。 -
Spider中間件(Spider middlewares)
Spider中間件是在引擎及Spider之間的特定鉤子(specific hook),處理spider的輸入(response)和輸出(items及requests)。 其提供了一個簡便的機制,通過插入自定義代碼來擴展Scrapy功能。更多內(nèi)容請看?Spider中間件(Middleware)?。
三:實例分析
1.從網(wǎng)站的主頁進入最新斗圖表情后網(wǎng)址是https://www.doutula.com/photo/list/?,點擊第二頁后看到網(wǎng)址變成了https://www.doutula.com/photo/list/?page=2?,那我們就知道了網(wǎng)址的構(gòu)成最后的page就是不同的頁數(shù)。那么spider中的start_urls開始入口就如下定義,爬取1到20頁的圖片表情。想下載更多表情頁數(shù)你可以再增加。
start_urls = ['https://www.doutula.com/photo/list/?page={}'.format(i) for i in range(1, 20)]2.進入開發(fā)者模式分析網(wǎng)頁結(jié)構(gòu),可以看到如下結(jié)構(gòu)。右擊復(fù)制一下xpath地址即可得到全部的表情所在的a標簽內(nèi)容。a[1]表示第一個a,去掉[1]就是全部的a。
//*[@id="pic-detail"]/div/div[1]/div[2]/aPaste_Image.png
值得注意的是這里的表情有兩種:一個jpg,一個gif動圖。如果獲取圖片地址時只抓取a標簽下面第一個img的src就會出錯,所以我們要抓取img中的含有data-original的值。這里a標簽下面還一個p標簽是圖片簡介,我們也抓取下來作為圖片文件的名稱。
Paste_Image.png
四:實戰(zhàn)代碼
完整代碼地址?github.com/rieuse/learnPython
1.首先使用命令行工具輸入代碼創(chuàng)建一個新的Scrapy項目,之后創(chuàng)建一個爬蟲。
2.打開Doutu文件夾中的items.py,改為以下代碼,定義我們爬取的項目。
import scrapy class DoutuItem(scrapy.Item): img_url = scrapy.Field() name = scrapy.Field()3.打開spiders文件夾中的doutula.py,改為以下代碼,這個是爬蟲主程序。
# -*- coding: utf-8 -*- import os import scrapy import requests from ScrapyDoutu.items import DoutuItemsclass Doutu(scrapy.Spider):name = "doutu"allowed_domains = ["doutula.com", "sinaimg.cn"] start_urls = ['https://www.doutula.com/photo/list/?page={}'.format(i) for i in range(1, 40)] # 我們暫且爬取40頁圖片 def parse(self, response): i = 0 for content in response.xpath('//*[@id="pic-detail"]/div/div[1]/div[2]/a'): i += 1 item = DoutuItems() item['img_url'] = 'http:' + content.xpath('//img/@data-original').extract()[i] item['name'] = content.xpath('//p/text()').extract()[i] try: if not os.path.exists('doutu'): os.makedirs('doutu') r = requests.get(item['img_url']) filename = 'doutu\\{}'.format(item['name']) + item['img_url'][-4:] with open(filename, 'wb') as fo: fo.write(r.content) except: print('Error') yield item3.這里面有很多值得注意的部分:
- 因為圖片的地址是放在sinaimg.cn中,所以要加入allowed_domains的列表中
- content.xpath('//img/@data-original').extract()[i]中extract()用來返回一個list(就是系統(tǒng)自帶的那個) 里面是一些你提取的內(nèi)容,[i]是結(jié)合前面的i的循環(huán)每次獲取下一個標簽內(nèi)容,如果不這樣設(shè)置,就會把全部的標簽內(nèi)容放入一個字典的值中。
- filename = 'doutu\{}'.format(item['name']) + item['img_url'][-4:]?是用來獲取圖片的名稱,最后item['img_url'][-4:]是獲取圖片地址的最后四位這樣就可以保證不同的文件格式使用各自的后綴。
- 最后一點就是如果xpath沒有正確匹配,則會出現(xiàn)<GET http://*****> (referer: None)
4.配置settings.py,如果想抓取快一點CONCURRENT_REQUESTS設(shè)置大一些,DOWNLOAD_DELAY設(shè)置小一些,或者為0.
# -*- coding: utf-8 -*- BOT_NAME = 'ScrapyDoutu'SPIDER_MODULES = ['ScrapyDoutu.spiders'] NEWSPIDER_MODULE = 'ScrapyDoutu.spiders'DOWNLOADER_MIDDLEWARES = { 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None, 'ScrapyDoutu.middlewares.RotateUserAgentMiddleware': 400, } ROBOTSTXT_OBEY = False # 不遵循網(wǎng)站的robots.txt策略 CONCURRENT_REQUESTS = 16 #Scrapy downloader 并發(fā)請求(concurrent requests)的最大值 DOWNLOAD_DELAY = 0.2 # 下載同一個網(wǎng)站頁面前等待的時間,可以用來限制爬取速度減輕服務(wù)器壓力。 COOKIES_ENABLED = False # 關(guān)閉cookies5.配置middleware.py配合settings中的UA設(shè)置可以在下載中隨機選擇UA有一定的反ban效果,在原有代碼基礎(chǔ)上加入下面代碼。這里的user_agent_list可以加入更多。
import random from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware class RotateUserAgentMiddleware(UserAgentMiddleware): def __init__(self, user_agent=''): self.user_agent = user_agent def process_request(self, request, spider): ua = random.choice(self.user_agent_list) if ua: print(ua) request.headers.setdefault('User-Agent', ua) user_agent_list = [ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1" "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24" ]6.到現(xiàn)在為止,代碼都已經(jīng)完成了。那么開始執(zhí)行吧!
scrapy crawl doutu
之后可以看到一邊下載,一邊修改User Agent。
Paste_Image.png
五:總結(jié)
學(xué)習(xí)使用Scrapy遇到很多坑,但是強大的搜索系統(tǒng)不會讓我感覺孤單。所以感覺Scrapy還是很強大的也很意思,后面繼續(xù)學(xué)習(xí)Scrapy的其他方面內(nèi)容。源碼加群
學(xué)習(xí)過程中遇到什么問題或者想獲取學(xué)習(xí)資源的話,歡迎加入學(xué)習(xí)交流群
626062078,我們一起學(xué)Python!
轉(zhuǎn)載于:https://www.cnblogs.com/jiaoyu121/p/6992587.html
總結(jié)
以上是生活随笔為你收集整理的Scrapy爬虫:抓取大量斗图网站最新表情图片的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分享一个在线代码测试
- 下一篇: Spring基于AspectJ实现AOP