
還等什么,Scrapy啟動(dòng),爬取開(kāi)始!
目標(biāo)網(wǎng)站
這里我們選取的目標(biāo)網(wǎng)站是我常逛的干貨集中營(yíng),而要爬取的就是她:

準(zhǔn)確的說(shuō)是她們,點(diǎn)擊右上角“今日力薦”,可以跳轉(zhuǎn)至往期“干貨”,這里就不再貼圖了,下面我們先簡(jiǎn)單說(shuō)下Scrapy的架構(gòu)和各部分功能。
架構(gòu)說(shuō)明

- Scrapy Engine(引擎): 負(fù)責(zé)Spider、ItemPipeline、Downloader、Scheduler中間的通訊,信號(hào)、數(shù)據(jù)傳遞等。
- Scheduler(調(diào)度器): 它負(fù)責(zé)接受引擎發(fā)送過(guò)來(lái)的Request請(qǐng)求,并按照一定的方式進(jìn)行整理排列,入隊(duì),當(dāng)引擎需要時(shí),交還給引擎。
- Downloader(下載器):負(fù)責(zé)下載Scrapy Engine(引擎)發(fā)送的所有Requests請(qǐng)求,并將其獲取到的Responses交還給Scrapy Engine(引擎),由引擎交給Spider來(lái)處理,
- Spider(爬蟲(chóng)):它負(fù)責(zé)處理所有Responses,從中分析提取數(shù)據(jù),獲取Item字段需要的數(shù)據(jù),并將需要跟進(jìn)的URL提交給引擎,再次進(jìn)入Scheduler(調(diào)度器).
- Item Pipeline(管道):它負(fù)責(zé)處理Spider中獲取到的Item,并進(jìn)行進(jìn)行后期處理(詳細(xì)分析、過(guò)濾、存儲(chǔ)等)的地方。
- Downloader Middlewares(下載中間件):你可以當(dāng)作是一個(gè)可以自定義擴(kuò)展下載功能的組件。
- Spider Middlewares(Spider中間件):你可以理解為是一個(gè)可以自定擴(kuò)展和操作引擎和Spider中間通信的功能組件(比如進(jìn)入Spider的Responses;和從Spider出去的Requests)
下面正式開(kāi)始爬取工作。
創(chuàng)建項(xiàng)目
在工作目錄shift+鼠標(biāo)右鍵打開(kāi)命令窗口,輸入
scrapy startproject girls
之后一個(gè)名為“girls”的Scrapy項(xiàng)目就已經(jīng)創(chuàng)建了。
打開(kāi)PyCharm選擇“open”方式打開(kāi)已創(chuàng)建項(xiàng)目(這里不建議用把項(xiàng)目直接拖到PyCharm的方式打開(kāi),筆者因此遇到了已經(jīng)下好的庫(kù)無(wú)法載入的問(wèn)題)。好了,讓我們看下載入好的項(xiàng)目目錄:

- scrapy.cfg: 項(xiàng)目的配置文件。
- girls/:項(xiàng)目的Python模塊,后續(xù)代碼在該目錄添加。
- girls/items.py:項(xiàng)目中的item文件,保存爬取數(shù)據(jù)的容器。
- girls/pipelines.py:項(xiàng)目中的pipelines文件,用于處理獲取的item。
- girls/settings.py:項(xiàng)目的設(shè)置文件。
- girls/spiders/:放置spider代碼的目錄。
明確目標(biāo)
通過(guò)定義Item明確爬取目標(biāo)。Item使用方法類(lèi)似Python的字典,另外它還提供了額外保護(hù)機(jī)制防止拼寫(xiě)錯(cuò)誤。這里只需要爬取圖片,所以源碼為:
import scrapy
class GirlsItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 圖片url
image_urls = scrapy.Field()
# 圖片信息
images = scrapy.Field()
- image_urls :圖片url,爬蟲(chóng)(spider)抓取項(xiàng)目后會(huì)將對(duì)應(yīng)url放入image_urls 中
- images :圖片信息,圖片下載完后更新到images結(jié)構(gòu)中。它包含一個(gè)字典列表,其中包括下載路徑、源抓取地址(image_urls中獲得)、圖片校驗(yàn)碼,并且圖片順序與image_urls保持一致。如果下載失敗,將記錄錯(cuò)誤信息,不再出現(xiàn)在images 中。
(這里用到了ImagesPipeline,下面會(huì)詳情講)
制作爬蟲(chóng)
即編寫(xiě)girls/spiders/目錄下的spider,spider類(lèi)定義了爬取網(wǎng)站的邏輯,包括爬取的動(dòng)作(如是否跟進(jìn)鏈接),將網(wǎng)頁(yè)內(nèi)容提取成結(jié)構(gòu)化數(shù)據(jù)(爬取Item)等。
這里建議通過(guò)命令直接生成spider文件:
點(diǎn)擊打開(kāi)PyCharm左下角Terminal窗口,輸入
scrapy genspider girl gank.io/
在girls/spiders/目錄下會(huì)生成對(duì)應(yīng)girl.py文件,文件內(nèi)容:
# -*- coding: utf-8 -*-
import scrapy
class GirlSpider(scrapy.Spider):
name = 'girl'
allowed_domains = ['gank.io/']
start_urls = ['http://gank.io//']
def parse(self, response):
pass
當(dāng)然手動(dòng)創(chuàng)建也是一樣的效果,命令只是省去了書(shū)寫(xiě)樣板代碼過(guò)程。解釋下代碼:
- name:爬蟲(chóng)名字,必須且唯一,后續(xù)命令也以此名字為準(zhǔn)。
- allowed_domains:爬蟲(chóng)允許的域名列表,域名不在列表時(shí)將不再跟進(jìn),可選。
- start_urls:爬取的url列表,未制定特定url時(shí),爬蟲(chóng)從該列表開(kāi)始爬取。
- parse(self, response):負(fù)責(zé)處理response并返回?cái)?shù)據(jù)以及跟進(jìn)的url(如果需要的話)。
在生成文件基礎(chǔ)上添加我們的爬取邏輯:
# -*- coding: utf-8 -*-
import scrapy
from girls.items import GirlsItem
class GirlSpider(scrapy.Spider):
name = 'girl'
allowed_domains = []
start_urls = ['http://gank.io//']
def parse(self, response):
item = GirlsItem()
item["image_urls"] = response.xpath("/html/body/div[1]/div[1]/div[2]/p[1]/img/@src").extract()
print(item)
yield item
new_url = response.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/p/a/@href").extract_first()
if new_url:
# 將相對(duì)路徑轉(zhuǎn)為絕對(duì)路徑
new_url = response.urljoin(new_url)
print(new_url)
yield scrapy.Request(new_url, callback=self.parse)
簡(jiǎn)單說(shuō)下代碼中網(wǎng)頁(yè)元素xpath獲取方法,這里用的瀏覽器是Chrome。
- 在想要獲取xpath的網(wǎng)頁(yè)元素上點(diǎn)擊右鍵,選擇檢查;
-
在被選擇的標(biāo)簽上右鍵,Copy →Copy XPath,
粘貼至代碼中即可。
存儲(chǔ)內(nèi)容
這里主要指設(shè)計(jì)管道( item pipeline)存儲(chǔ)爬取到的內(nèi)容,即上邊提到的ImagesPipeline。
ImagesPipeline即Scrapy提供的一個(gè)item pipeline,用來(lái)下載某個(gè)特定項(xiàng)目中的圖片并保存到本地,并且具有如下特點(diǎn):
- 將所有下載的圖片轉(zhuǎn)換成通用的格式(JPG)和模式(RGB)
- 避免重新下載最近已經(jīng)下載過(guò)的圖片
- 縮略圖生成
- 檢測(cè)圖像的寬/高,確保它們滿足最小限制
這里如果需要生成縮略圖,請(qǐng)下載Pillow庫(kù),下載方法“安裝篇”里有提到。
使用ImagesPipeline除了items.py中的代碼外,只需要在settings.py配置相關(guān)設(shè)置即可,貼上源碼根據(jù)需求設(shè)置:
# 開(kāi)啟圖片管道 ImagesPipeline地址項(xiàng)目實(shí)際地址為準(zhǔn)
ITEM_PIPELINES = {'scrapy.pipelines.images.ImagesPipeline': 300}
# 設(shè)置圖片存儲(chǔ)目錄,一個(gè)有效的文件夾
IMAGES_STORE = 'girls/bitmap'
# 圖片開(kāi)始下載延時(shí)
# DOWNLOAD_DELAY = 0.25
#縮略圖的尺寸,設(shè)置這個(gè)值就會(huì)產(chǎn)生縮略圖
# IMAGES_THUMBS = {
# 'small': (50, 50),
# 'big': (200, 200),
# }
# 90天的圖片失效期限
# 避免下載最近已經(jīng)下載的圖片
# IMAGES_EXPIRES = 90
# 濾出小圖片
# IMAGES_MIN_HEIGHT = 110
# IMAGES_MIN_WIDTH = 110
注意:開(kāi)啟圖片管道設(shè)置ImagesPipeline地址應(yīng)以項(xiàng)目實(shí)際地址為準(zhǔn)這里是scrapy.pipelines.images.ImagesPipeline,這點(diǎn)官方中文文檔有誤。
另外如果需要定制圖片管道請(qǐng)參考官方文檔的 實(shí)現(xiàn)定制圖片管道,這里不再贅述。
開(kāi)始爬取(?ω?)
雖然直接在命令行中輸入命令即可開(kāi)始爬取,但是既然我們使用了PyCharm不妨使用IDE的方式:
- 在scrapy.cfg文件同級(jí)目錄創(chuàng)建start.py文件,輸入
# -*- coding:utf-8 -*-
from scrapy import cmdline
cmdline.execute("scrapy crawl girl".split())
-
右上角
左邊或者Run菜單中選擇 -
彈出菜單點(diǎn)擊加+號(hào),選擇
Python -
做如下設(shè)置
設(shè)置完,OK結(jié)束。
-
點(diǎn)擊右上角
即可開(kāi)始爬取。
稍等片刻圖片就爬取完啦,如圖?(????ω????)?

總結(jié)
綜上可見(jiàn)一個(gè)標(biāo)準(zhǔn)的Scrapy爬取流程是:
- 創(chuàng)建項(xiàng)目 (scrapy startproject xxx):新建一個(gè)新的爬蟲(chóng)項(xiàng)目
- 明確目標(biāo) (編寫(xiě)items.py):明確你想要抓取并存儲(chǔ)的目標(biāo)
- 制作爬蟲(chóng) (spiders/xxspider.py):制作爬蟲(chóng),明確爬取的網(wǎng)頁(yè)元素及爬取動(dòng)作
- 存儲(chǔ)內(nèi)容 (pipelines.py):設(shè)計(jì)管道存儲(chǔ)爬取內(nèi)容
那么以上各個(gè)部分在爬取過(guò)程中是如何運(yùn)行和配合的呢?
結(jié)合上面提到的架構(gòu)圖可知:
- Scrapy引擎從爬蟲(chóng)(Spider)文件中獲取開(kāi)始的url,并交由調(diào)度器和下載器處理,處理好后得到的response交還爬蟲(chóng);
- 爬蟲(chóng)根據(jù)爬蟲(chóng)文件中設(shè)置的爬取動(dòng)作,爬取
image_urls并儲(chǔ)存至items中,需要跟進(jìn)的url提交給引擎; - Scrapy引擎將items中
image_urls交給管道(Item Pipeline)處理,跟進(jìn)的url交給調(diào)度器; - 管道這里根據(jù)ImagesPipeline及settings.py中的設(shè)置處理并將
image_urls通過(guò)引擎交由調(diào)度器和下載器下載,項(xiàng)目會(huì)在這個(gè)特定的管道階段保持“l(fā)ocker”的狀態(tài),直到完成圖片的下載(或者由于某些原因未完成下載),下載完后,圖片信息更新到images中。之后調(diào)度器根據(jù)需跟進(jìn)的url從1.開(kāi)始循環(huán),直到調(diào)度器中不再有任何request,爬取結(jié)束。

參考文章:
官方文檔:https://scrapy-chs.readthedocs.io/zh_CN/0.24/index.html
Scrapy 入門(mén)教程:http://www.runoob.com/w3cnote/scrapy-detail.html
Scrapy爬取美女:https://www.cnblogs.com/qiyeboy/p/5428240.html





