引言
它是一個(gè)功能強(qiáng)大的Python框架,用于以非常靈活的方式從任何網(wǎng)站提取數(shù)據(jù)。它使用 Xpath 來搜索和提取數(shù)據(jù)。它很輕量級(jí),對于初學(xué)者來說很容易理解。
現(xiàn)在,為了了解 Scrapy 的工作原理,我們將使用這個(gè)框架來抓取 Amazon 數(shù)據(jù)。我們將抓取亞馬遜的圖書部分,更具體地說,我們將抓取過去 30 天內(nèi)發(fā)布的書籍。

實(shí)戰(zhàn)
我們將從創(chuàng)建一個(gè)文件夾并安裝 Scrapy 開始。
mkdir scraper
pip install scrapy
現(xiàn)在,在開始編碼之前,我們必須創(chuàng)建一個(gè)項(xiàng)目。只需在終端中輸入以下命令即可。
scrapy startproject amazonscraper
此命令將在 scraper 文件夾內(nèi)創(chuàng)建一個(gè)名為 amazonscraper 的項(xiàng)目文件夾。

上面的命令還在終端上返回一些消息,告訴您如何開始編寫自己的抓取工具。我們將使用這兩個(gè)命令。
讓我們先進(jìn)入這個(gè) amazonscraper 文件夾。
cd amazonscraper
scrapy genspider amazon_spider amazon.com
這將為我們創(chuàng)建一個(gè)通用的spider,這樣我們就不必通過進(jìn)入spider文件夾來創(chuàng)建我們自己的spider,這將自動(dòng)為我們創(chuàng)建它。然后我們?yōu)?code>spider命名,然后輸入目標(biāo)網(wǎng)站的域名。
當(dāng)您按 Enter 鍵時(shí),您的文件夾中將出現(xiàn)一個(gè)名為 amazon_spider.py 的文件。當(dāng)您打開該文件時(shí),您會(huì)發(fā)現(xiàn)已自動(dòng)創(chuàng)建了一個(gè)解析函數(shù)和一個(gè) Amazonspider 類。
import scrapy
class AmazonSpiderSpider(scrapy.Spider):
name = ‘a(chǎn)mazon_spider’
allowed_domains = [‘a(chǎn)mazon.com’]
start_urls = [‘http://amazon.com/']
def parse(self, response):
pass
我們將刪除 allowed_domains 變量,因?yàn)槲覀儾恍枰?,同時(shí)我們將聲明 start_urls 到我們的目標(biāo) URL。
//amazon_spider.py
import scrapy
class AmazonSpiderSpider(scrapy.Spider):
name = ‘a(chǎn)mazon_spider’
allowed_domains = [‘a(chǎn)mazon.com’]
start_urls = [‘https://www.amazon.com/s?k=books&i=stripbooks-intl-ship&__mk_es_US=%C3%85M%C3%85%C5%BD%C3%95%C3%91&crid=11NL2VKJ00J&sprefix=bo%2Cstripbooks-intl-ship%2C443&ref=nb_sb_noss_2']
def parse(self, response):
pass
在開始使用抓取工具之前,我們需要在 items.py 文件中創(chuàng)建一些項(xiàng)目,它們是臨時(shí)容器。我們將從亞馬遜頁面上抓取標(biāo)題、價(jià)格、作者和圖像鏈接。
由于我們需要來自亞馬遜的四件商品,因此我們將添加四個(gè)變量來存儲(chǔ)值。
//items.py
import scrapy
class AmazonscraperItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
product_name = scrapy.Field()
product_author = scrapy.Field()
product_price = scrapy.Field()
product_imagelink = scrapy.Field()
pass
現(xiàn)在,我們將該文件導(dǎo)入到 amazon_spider.py 文件中。
//amazon_spider.py
from ..items import AmazonscraperItem
只需在文件頂部鍵入它即可。現(xiàn)在,在我們的 parse 方法中,我們將聲明一個(gè)變量,它將成為 AmazonscraperItem 類的實(shí)例。
def parse(self, response):
items = AmazonscraperItem()
pass
我們現(xiàn)在準(zhǔn)備從亞馬遜上抓取我們的目標(biāo)元素。我們將從抓取產(chǎn)品名稱開始。我們將聲明一個(gè)變量product_name,它將等于產(chǎn)品名稱元素的CSS 選擇器。
def parse(self, response):
items = AmazonscraperItem()
product_name= response.css()
pass
在這里,我將使用 SelectorGadget 擴(kuò)展來獲取目標(biāo)頁面上的元素位置。

在右下角你可以看到我們的 CSS 選擇器。我將從這里復(fù)制它,然后將其粘貼到我們的代碼中。
def parse(self, response):
items = AmazonscraperItem()
product_name= response.css(‘.a-size-medium’).extract()
pass
我使用 .extract() 函數(shù)來獲取所有這些產(chǎn)品元素的 HTML 部分。同樣,我們將使用相同的技術(shù)來提取產(chǎn)品價(jià)格、作者和圖像鏈接。在為作者查找 CSS 選擇器時(shí),SelectorGadget 會(huì)選擇其中的一些,而會(huì)讓許多作者未被選中。因此,您還必須選擇這些作者。

def parse(self, response):
items = AmazonscraperItem()
product_name= response.css(‘.a-size-medium’).extract()
product_author = response.css(‘.a-color-secondary .a-row .a-size-base+ .a-size-base , .a-color-secondary .a-size-base.s-link-style , .a-color-secondary .a-size-base.s-link-style font’).extract()
pass
現(xiàn)在,我們也找到價(jià)格的 CSS 選擇器。

def parse(self, response):
items = AmazonscraperItem()
product_name= response.css(‘.a-size-medium’).extract()
product_author = response.css(‘.a-color-secondary .a-row .a-size-base+ .a-size-base , .a-color-secondary .a-size-base.s-link-style , .a-color-secondary .a-size-base.s-link-style font’).extract()
product_price = response.css(‘.s-price-instructions-style .a-price-fraction , .s-price-instructions-style .a-price-whole’).extract()
pass
最后,現(xiàn)在我們將找到圖像的 CSS 選擇器。

.s-image 是我們圖像的 CSS 選擇器。
def parse(self, response):
items = AmazonscraperItem()
product_name= response.css(‘.a-size-medium’).extract()
product_author = response.css(‘.a-color-secondary .a-row .a-size-base+ .a-size-base , .a-color-secondary .a-size-base.s-link-style , .a-color-secondary .a-size-base.s-link-style font’).extract()
product_price = response.css(‘.s-price-instructions-style .a-price-fraction , .s-price-instructions-style .a-price-whole’).extract()
product_imagelink = response.css(‘.s-image’).extract()
現(xiàn)在,正如我之前所說,這只會(huì)為我們提供 HTML 代碼,我們需要從中提取名稱。因此,為此,我們將使用 Scrapy 的文本功能。這將確保不會(huì)提取整個(gè)標(biāo)簽,并且僅提取該標(biāo)簽中的文本。
product_name= response.css(‘.a-size-medium::text’).extract()
但是因?yàn)槲覀優(yōu)?CSS 選擇器使用了多個(gè)類,所以我們無法在末尾添加此文本。我們必須對product_price 和product_author 使用.css() 函數(shù)。
product_author = response.css(‘.a-color-secondary .a-row .a-size-base+ .a-size-base , .a-color-secondary .a-size-base.s-link-style , .a-color-secondary .a-size-base.s-link-style font’).css(‘::text’).extract()
product_price = response.css(‘.s-price-instructions-style .a-price-fraction , .s-price-instructions-style .a-price-whole’).css(‘::text’).extract()
現(xiàn)在,product_imagelink 只是選擇圖像,因此我們不會(huì)在其上使用 .css() 函數(shù)。我們的圖像存儲(chǔ)在 src 標(biāo)簽內(nèi),我們需要它的值。

我們將使用Scrapy的attr功能。
product_imagelink = response.css(‘.s-image::attr(src)’).extract()
我們已經(jīng)成功提取了所有值?,F(xiàn)在,我們將它們存儲(chǔ)在各自的臨時(shí)物品容器中,這就是我們的做法。
items[‘product_name’] = product_name
這個(gè)product_name實(shí)際上是我們在items.py文件中聲明的變量。我們將對所有其他目標(biāo)元素執(zhí)行此操作。
items[‘product_name’] = product_name
items[‘product_author’] = product_author
items[‘product_price’] = product_price
items[‘product_imagelink’] = product_imagelink
現(xiàn)在,我們只需要生成這些項(xiàng)目,這將完成我們的代碼。我們的代碼一開始可能不會(huì),但讓我們看看我們得到了什么。
yield items
現(xiàn)在,要運(yùn)行我們的代碼,請?jiān)诮K端上運(yùn)行以下命令。
scrapy crawl amazon_spider

正如你所看到的,我們得到了一個(gè)空數(shù)組。這是由于亞馬遜的反機(jī)器人機(jī)制所致。為了克服這個(gè)問題,我們將在 settings.py 文件中設(shè)置一個(gè)用戶代理。
USER_AGENT = ‘Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0’
現(xiàn)在,讓我們再試一次。

我們得到了結(jié)果。但和往常一樣,這不會(huì)持續(xù)多久,因?yàn)閬嗰R遜的反機(jī)器人技術(shù)將會(huì)啟動(dòng),你的抓取工具將會(huì)停止。
Scrapy的功能還不止于此!
- 您可以通過更改 CONCURRENT_REQUESTS 的值在 settings.py 文件中設(shè)置并行請求數(shù)。這將幫助您檢查 API 可以處理多少負(fù)載。
- 它比 Python 提供的大多數(shù) HTTP 庫都要快。