第42讲:scrapy框架的基本使用
接下來(lái)介紹一個(gè)簡(jiǎn)單的項(xiàng)目,完成一遍 Scrapy 抓取流程。通過(guò)這個(gè)過(guò)程,我們可以對(duì) Scrapy 的基本用法和原理有大體了解。
本節(jié)目標(biāo)
本節(jié)要完成的任務(wù)如下。
- 創(chuàng)建一個(gè) Scrapy 項(xiàng)目。
- 創(chuàng)建一個(gè) Spider 來(lái)抓取站點(diǎn)和處理數(shù)據(jù)。
- 通過(guò)命令行將抓取的內(nèi)容導(dǎo)出。
- 將抓取的內(nèi)容保存到 MongoDB 數(shù)據(jù)庫(kù)。
本節(jié)抓取的目標(biāo)站點(diǎn)為 http://quotes.toscrape.com/。
準(zhǔn)備工作
我們需要安裝好 Scrapy 框架、MongoDB 和 PyMongo 庫(kù)。如果尚未安裝,請(qǐng)參照之前幾節(jié)的安裝說(shuō)明。
創(chuàng)建項(xiàng)目
創(chuàng)建一個(gè) Scrapy 項(xiàng)目,項(xiàng)目文件可以直接用 scrapy 命令生成,命令如下所示:
scrapy startproject tutorial這個(gè)命令可以在任意文件夾運(yùn)行。如果提示權(quán)限問(wèn)題,可以加 sudo 運(yùn)行該命令。這個(gè)命令將會(huì)創(chuàng)建一個(gè)名為 tutorial 的文件夾,文件夾結(jié)構(gòu)如下所示:
scrapy.cfg # Scrapy 部署時(shí)的配置文件 tutorial # 項(xiàng)目的模塊,引入的時(shí)候需要從這里引入__init__.py items.py # Items 的定義,定義爬取的數(shù)據(jù)結(jié)構(gòu)middlewares.py # Middlewares 的定義,定義爬取時(shí)的中間件pipelines.py # Pipelines 的定義,定義數(shù)據(jù)管道settings.py # 配置文件spiders # 放置 Spiders 的文件夾__init__.py創(chuàng)建 Spider
Spider 是自己定義的類,Scrapy 用它從網(wǎng)頁(yè)里抓取內(nèi)容,并解析抓取的結(jié)果。不過(guò)這個(gè)類必須繼承 Scrapy 提供的 Spider 類 scrapy.Spider,還要定義 Spider 的名稱和起始請(qǐng)求,以及怎樣處理爬取后的結(jié)果的方法。
你也可以使用命令行創(chuàng)建一個(gè) Spider。比如要生成 Quotes 這個(gè) Spider,可以執(zhí)行如下命令:
cd tutorial scrapy genspider quotes進(jìn)入剛才創(chuàng)建的 tutorial 文件夾,然后執(zhí)行 genspider 命令。第一個(gè)參數(shù)是 Spider 的名稱,第二個(gè)參數(shù)是網(wǎng)站域名。執(zhí)行完畢之后,spiders 文件夾中多了一個(gè) quotes.py,它就是剛剛創(chuàng)建的 Spider,內(nèi)容如下所示:
import scrapy ? class QuotesSpider(scrapy.Spider):name = "quotes"allowed_domains = ["quotes.toscrape.com"]start_urls = ['http://quotes.toscrape.com/'] ?def parse(self, response):pass這里有三個(gè)屬性——name、allowed_domains 和 start_urls,還有一個(gè)方法 parse。
- name:它是每個(gè)項(xiàng)目唯一的名字,用來(lái)區(qū)分不同的 Spider。
- allowed_domains:它是允許爬取的域名,如果初始或后續(xù)的請(qǐng)求鏈接不是這個(gè)域名下的,則請(qǐng)求鏈接會(huì)被過(guò)濾掉。
- start_urls:它包含了 Spider 在啟動(dòng)時(shí)爬取的 url 列表,初始請(qǐng)求是由它來(lái)定義的。
- parse:它是 Spider 的一個(gè)方法。默認(rèn)情況下,被調(diào)用時(shí) start_urls 里面的鏈接構(gòu)成的請(qǐng)求完成下載執(zhí)行后,返回的響應(yīng)就會(huì)作為唯一的參數(shù)傳遞給這個(gè)函數(shù)。該方法負(fù)責(zé)解析返回的響應(yīng)、提取數(shù)據(jù)或者進(jìn)一步生成要處理的請(qǐng)求。
創(chuàng)建 Item
Item 是保存爬取數(shù)據(jù)的容器,它的使用方法和字典類似。不過(guò),相比字典,Item 多了額外的保護(hù)機(jī)制,可以避免拼寫(xiě)錯(cuò)誤或者定義字段錯(cuò)誤。
創(chuàng)建 Item 需要繼承 scrapy.Item 類,并且定義類型為 scrapy.Field 的字段。觀察目標(biāo)網(wǎng)站,我們可以獲取到的內(nèi)容有 text、author、tags。
定義 Item,此時(shí)將 items.py 修改如下:
import scrapy ? class QuoteItem(scrapy.Item): ?text = scrapy.Field()author = scrapy.Field()tags = scrapy.Field()這里定義了三個(gè)字段,將類的名稱修改為 QuoteItem,接下來(lái)爬取時(shí)我們會(huì)使用到這個(gè) Item。
解析 Response
前面我們看到,parse 方法的參數(shù) response 是 start_urls 里面的鏈接爬取后的結(jié)果。所以在 parse 方法中,我們可以直接對(duì) response 變量包含的內(nèi)容進(jìn)行解析,比如瀏覽請(qǐng)求結(jié)果的網(wǎng)頁(yè)源代碼,或者進(jìn)一步分析源代碼內(nèi)容,或者找出結(jié)果中的鏈接而得到下一個(gè)請(qǐng)求。
我們可以看到網(wǎng)頁(yè)中既有我們想要的結(jié)果,又有下一頁(yè)的鏈接,這兩部分內(nèi)容我們都要進(jìn)行處理。
首先看看網(wǎng)頁(yè)結(jié)構(gòu),如圖所示。每一頁(yè)都有多個(gè) class 為 quote 的區(qū)塊,每個(gè)區(qū)塊內(nèi)都包含 text、author、tags。那么我們先找出所有的 quote,然后提取每一個(gè) quote 中的內(nèi)容。
提取的方式可以是 CSS 選擇器或 XPath 選擇器。在這里我們使用 CSS 選擇器進(jìn)行選擇,parse 方法的改寫(xiě)如下所示:
這里首先利用選擇器選取所有的 quote,并將其賦值為 quotes 變量,然后利用 for 循環(huán)對(duì)每個(gè) quote 遍歷,解析每個(gè) quote 的內(nèi)容。
對(duì) text 來(lái)說(shuō),觀察到它的 class 為 text,所以可以用 .text 選擇器來(lái)選取,這個(gè)結(jié)果實(shí)際上是整個(gè)帶有標(biāo)簽的節(jié)點(diǎn),要獲取它的正文內(nèi)容,可以加 ::text 來(lái)獲取。這時(shí)的結(jié)果是長(zhǎng)度為 1 的列表,所以還需要用 extract_first 方法來(lái)獲取第一個(gè)元素。而對(duì)于 tags 來(lái)說(shuō),由于我們要獲取所有的標(biāo)簽,所以用 extract 方法獲取整個(gè)列表即可。
以第一個(gè) quote 的結(jié)果為例,各個(gè)選擇方法及結(jié)果的說(shuō)明如下內(nèi)容。
源碼如下:
<div class="quote" itemscope=""itemtype="http://schema.org/CreativeWork"><span class="text" itemprop="text">“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”</span><span>by <small class="author" itemprop="author">Albert Einstein</small><a href="/author/Albert-Einstein">(about)</a></span><div class="tags">Tags:<meta class="keywords" itemprop="keywords" content="change,deep-thoughts,thinking,world"> <a class="tag" href="/tag/change/page/1/">change</a><a class="tag" href="/tag/deep-thoughts/page/1/">deep-thoughts</a><a class="tag" href="/tag/thinking/page/1/">thinking</a><a class="tag" href="/tag/world/page/1/">world</a></div></div>不同選擇器的返回結(jié)果如下。
quote.css(’.text’)
[<Selector xpath="descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), ' text ')]"data='<span class="text"itemprop="text">“The '>]quote.css(’.text::text’)
[<Selector xpath="descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), ' text ')]/text()"data='“The world as we have created it is a pr'>]quote.css(’.text’).extract()
['<span class="text"itemprop="text">“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”</span>']quote.css(’.text::text’).extract()
['“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”']quote.css(’.text::text’).extract_first()
“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”使用 Item
上文定義了 Item,接下來(lái)就要使用它了。Item 可以理解為一個(gè)字典,不過(guò)在聲明的時(shí)候需要實(shí)例化。然后依次用剛才解析的結(jié)果賦值 Item 的每一個(gè)字段,最后將 Item 返回即可。
QuotesSpider 的改寫(xiě)如下所示: import scrapy from tutorial.items import QuoteItem ? class QuotesSpider(scrapy.Spider):name = "quotes"allowed_domains = ["quotes.toscrape.com"]start_urls = ['http://quotes.toscrape.com/'] ?def parse(self, response):quotes = response.css('.quote')for quote in quotes:item = QuoteItem()item['text'] = quote.css('.text::text').extract_first()item['author'] = quote.css('.author::text').extract_first()item['tags'] = quote.css('.tags .tag::text').extract()yield item如此一來(lái),首頁(yè)的所有內(nèi)容被解析出來(lái),并被賦值成了一個(gè)個(gè) QuoteItem。
后續(xù) Request
上面的操作實(shí)現(xiàn)了從初始頁(yè)面抓取內(nèi)容。那么,下一頁(yè)的內(nèi)容該如何抓取?這就需要我們從當(dāng)前頁(yè)面中找到信息來(lái)生成下一個(gè)請(qǐng)求,然后在下一個(gè)請(qǐng)求的頁(yè)面里找到信息再構(gòu)造下一個(gè)請(qǐng)求。這樣循環(huán)往復(fù)迭代,從而實(shí)現(xiàn)整站的爬取。
將剛才的頁(yè)面拉到最底部,如圖所示。
有一個(gè) Next 按鈕,查看一下源代碼,可以發(fā)現(xiàn)它的鏈接是 /page/2/,實(shí)際上全鏈接就是:http://quotes.toscrape.com/page/2,通過(guò)這個(gè)鏈接我們就可以構(gòu)造下一個(gè)請(qǐng)求。
構(gòu)造請(qǐng)求時(shí)需要用到 scrapy.Request。這里我們傳遞兩個(gè)參數(shù)——url 和 callback,這兩個(gè)參數(shù)的說(shuō)明如下。
- url:它是請(qǐng)求鏈接。
- callback:它是回調(diào)函數(shù)。當(dāng)指定了該回調(diào)函數(shù)的請(qǐng)求完成之后,獲取到響應(yīng),引擎會(huì)將該響應(yīng)作為參數(shù)傳遞給這個(gè)回調(diào)函數(shù)。回調(diào)函數(shù)進(jìn)行解析或生成下一個(gè)請(qǐng)求,回調(diào)函數(shù)如上文的 parse() 所示。
由于 parse 就是解析 text、author、tags 的方法,而下一頁(yè)的結(jié)構(gòu)和剛才已經(jīng)解析的頁(yè)面結(jié)構(gòu)是一樣的,所以我們可以再次使用 parse 方法來(lái)做頁(yè)面解析。
接下來(lái)我們要做的就是利用選擇器得到下一頁(yè)鏈接并生成請(qǐng)求,在 parse 方法后追加如下的代碼:
next = response.css('.pager .next a::attr(href)').extract_first() url = response.urljoin(next) yield scrapy.Request(url=url, callback=self.parse)第一句代碼首先通過(guò) CSS 選擇器獲取下一個(gè)頁(yè)面的鏈接,即要獲取 a 超鏈接中的 href 屬性。這里用到了 ::attr(href) 操作。然后再調(diào)用 extract_first 方法獲取內(nèi)容。
第二句代碼調(diào)用了 urljoin 方法,urljoin() 方法可以將相對(duì) URL 構(gòu)造成一個(gè)絕對(duì)的 URL。例如,獲取到的下一頁(yè)地址是 /page/2,urljoin 方法處理后得到的結(jié)果就是:http://quotes.toscrape.com/page/2/。
第三句代碼通過(guò) url 和 callback 變量構(gòu)造了一個(gè)新的請(qǐng)求,回調(diào)函數(shù) callback 依然使用 parse 方法。這個(gè)請(qǐng)求完成后,響應(yīng)會(huì)重新經(jīng)過(guò) parse 方法處理,得到第二頁(yè)的解析結(jié)果,然后生成第二頁(yè)的下一頁(yè),也就是第三頁(yè)的請(qǐng)求。這樣爬蟲(chóng)就進(jìn)入了一個(gè)循環(huán),直到最后一頁(yè)。
通過(guò)幾行代碼,我們就輕松實(shí)現(xiàn)了一個(gè)抓取循環(huán),將每個(gè)頁(yè)面的結(jié)果抓取下來(lái)了。現(xiàn)在,改寫(xiě)之后的整個(gè) Spider 類如下所示:
import scrapy from tutorial.items import QuoteItem ? class QuotesSpider(scrapy.Spider):name = "quotes"allowed_domains = ["quotes.toscrape.com"]start_urls = ['http://quotes.toscrape.com/'] ?def parse(self, response):quotes = response.css('.quote')for quote in quotes:item = QuoteItem()item['text'] = quote.css('.text::text').extract_first()item['author'] = quote.css('.author::text').extract_first()item['tags'] = quote.css('.tags .tag::text').extract()yield item ?next = response.css('.pager .next a::attr("href")').extract_first()url = response.urljoin(next)yield scrapy.Request(url=url, callback=self.parse)運(yùn)行
接下來(lái),進(jìn)入目錄,運(yùn)行如下命令:
scrapy crawl quotes就可以看到 Scrapy 的運(yùn)行結(jié)果了。
2020-02-19 13:37:20 [scrapy.utils.log] INFO: Scrapy 1.3.0 started (bot: tutorial) 2020-02-19 13:37:20 [scrapy.utils.log] INFO: Overridden settings: {'NEWSPIDER_MODULE': 'tutorial.spiders', 'SPIDER_MODULES': ['tutorial.spiders'], 'ROBOTSTXT_OBEY': True, 'BOT_NAME': 'tutorial'} 2020-02-19 13:37:20 [scrapy.middleware] INFO: Enabled extensions: ['scrapy.extensions.logstats.LogStats','scrapy.extensions.telnet.TelnetConsole','scrapy.extensions.corestats.CoreStats'] 2020-02-19 13:37:20 [scrapy.middleware] INFO: Enabled downloader middlewares: ['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware','scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware','scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware','scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware','scrapy.downloadermiddlewares.useragent.UserAgentMiddleware','scrapy.downloadermiddlewares.retry.RetryMiddleware','scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware','scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware','scrapy.downloadermiddlewares.redirect.RedirectMiddleware',這里只是部分運(yùn)行結(jié)果,中間一些抓取結(jié)果已省略。
首先,Scrapy 輸出了當(dāng)前的版本號(hào),以及正在啟動(dòng)的項(xiàng)目名稱。接著輸出了當(dāng)前 settings.py 中一些重寫(xiě)后的配置。然后輸出了當(dāng)前所應(yīng)用的 Middlewares 和 Pipelines。Middlewares 默認(rèn)是啟用的,可以在 settings.py 中修改。Pipelines 默認(rèn)是空,同樣也可以在 settings.py 中配置。后面會(huì)對(duì)它們進(jìn)行講解。
接下來(lái)就是輸出各個(gè)頁(yè)面的抓取結(jié)果了,可以看到爬蟲(chóng)一邊解析,一邊翻頁(yè),直至將所有內(nèi)容抓取完畢,然后終止。
最后,Scrapy 輸出了整個(gè)抓取過(guò)程的統(tǒng)計(jì)信息,如請(qǐng)求的字節(jié)數(shù)、請(qǐng)求次數(shù)、響應(yīng)次數(shù)、完成原因等。
整個(gè) Scrapy 程序成功運(yùn)行。我們通過(guò)非常簡(jiǎn)單的代碼就完成了一個(gè)網(wǎng)站內(nèi)容的爬取,這樣相比之前一點(diǎn)點(diǎn)寫(xiě)程序簡(jiǎn)潔很多。
保存到文件
運(yùn)行完 Scrapy 后,我們只在控制臺(tái)看到了輸出結(jié)果。如果想保存結(jié)果該怎么辦呢?
要完成這個(gè)任務(wù)其實(shí)不需要任何額外的代碼,Scrapy 提供的 Feed Exports 可以輕松將抓取結(jié)果輸出。例如,我們想將上面的結(jié)果保存成 JSON 文件,可以執(zhí)行如下命令:
scrapy crawl quotes -o quotes.json命令運(yùn)行后,項(xiàng)目?jī)?nèi)多了一個(gè) quotes.json 文件,文件包含了剛才抓取的所有內(nèi)容,內(nèi)容是 JSON 格式。
另外我們還可以每一個(gè) Item 輸出一行 JSON,輸出后綴為 jl,為 jsonline 的縮寫(xiě),命令如下所示:
scrapy crawl quotes -o quotes.jl或
scrapy crawl quotes -o quotes.jsonlines輸出格式還支持很多種,例如 csv、xml、pickle、marshal 等,還支持 ftp、s3 等遠(yuǎn)程輸出,另外還可以通過(guò)自定義 ItemExporter 來(lái)實(shí)現(xiàn)其他的輸出。
例如,下面命令對(duì)應(yīng)的輸出分別為 csv、xml、pickle、marshal 格式以及 ftp 遠(yuǎn)程輸出:
scrapy crawl quotes -o quotes.csv scrapy crawl quotes -o quotes.xml scrapy crawl quotes -o quotes.pickle scrapy crawl quotes -o quotes.marshal scrapy crawl quotes -o ftp://user:pass@ftp.example.com/path/to/quotes.csv其中,ftp 輸出需要正確配置用戶名、密碼、地址、輸出路徑,否則會(huì)報(bào)錯(cuò)。
通過(guò) Scrapy 提供的 Feed Exports,我們可以輕松地輸出抓取結(jié)果到文件。對(duì)于一些小型項(xiàng)目來(lái)說(shuō),這應(yīng)該足夠了。不過(guò)如果想要更復(fù)雜的輸出,如輸出到數(shù)據(jù)庫(kù)等,我們可以使用 Item Pileline 來(lái)完成。
使用 Item Pipeline
如果想進(jìn)行更復(fù)雜的操作,如將結(jié)果保存到 MongoDB 數(shù)據(jù)庫(kù),或者篩選某些有用的 Item,則我們可以定義 Item Pipeline 來(lái)實(shí)現(xiàn)。
Item Pipeline 為項(xiàng)目管道。當(dāng) Item 生成后,它會(huì)自動(dòng)被送到 Item Pipeline 進(jìn)行處理,我們常用 Item Pipeline 來(lái)做如下操作。
- 清洗 HTML 數(shù)據(jù);
- 驗(yàn)證爬取數(shù)據(jù),檢查爬取字段;
- 查重并丟棄重復(fù)內(nèi)容;
- 將爬取結(jié)果儲(chǔ)存到數(shù)據(jù)庫(kù)。
要實(shí)現(xiàn) Item Pipeline 很簡(jiǎn)單,只需要定義一個(gè)類并實(shí)現(xiàn) process_item 方法即可。啟用 Item Pipeline 后,Item Pipeline 會(huì)自動(dòng)調(diào)用這個(gè)方法。process_item 方法必須返回包含數(shù)據(jù)的字典或 Item 對(duì)象,或者拋出 DropItem 異常。
process_item 方法有兩個(gè)參數(shù)。一個(gè)參數(shù)是 item,每次 Spider 生成的 Item 都會(huì)作為參數(shù)傳遞過(guò)來(lái)。另一個(gè)參數(shù)是 spider,就是 Spider 的實(shí)例。
接下來(lái),我們實(shí)現(xiàn)一個(gè) Item Pipeline,篩掉 text 長(zhǎng)度大于 50 的 Item,并將結(jié)果保存到 MongoDB。
修改項(xiàng)目里的 pipelines.py 文件,之前用命令行自動(dòng)生成的文件內(nèi)容可以刪掉,增加一個(gè) TextPipeline 類,內(nèi)容如下所示:
from scrapy.exceptions import DropItem ? class TextPipeline(object):def __init__(self):self.limit = 50def process_item(self, item, spider):if item['text']:if len(item['text']) > self.limit:item['text'] = item['text'][0:self.limit].rstrip() + '...'return itemelse:return DropItem('Missing Text')這段代碼在構(gòu)造方法里定義了限制長(zhǎng)度為 50,實(shí)現(xiàn)了 process_item 方法,其參數(shù)是 item 和 spider。首先該方法判斷 item 的 text 屬性是否存在,如果不存在,則拋出 DropItem 異常;如果存在,再判斷長(zhǎng)度是否大于 50,如果大于,那就截?cái)嗳缓笃唇邮÷蕴?hào),再將 item 返回即可。
接下來(lái),我們將處理后的 item 存入 MongoDB,定義另外一個(gè) Pipeline。同樣在 pipelines.py 中,我們實(shí)現(xiàn)另一個(gè)類 MongoPipeline,內(nèi)容如下所示:
import pymongo ? class MongoPipeline(object):def __init__(self, mongo_uri, mongo_db):self.mongo_uri = mongo_uriself.mongo_db = mongo_db ?@classmethoddef from_crawler(cls, crawler):return cls(mongo_uri=crawler.settings.get('MONGO_URI'),mongo_db=crawler.settings.get('MONGO_DB')) ?def open_spider(self, spider):self.client = pymongo.MongoClient(self.mongo_uri)self.db = self.client[self.mongo_db] ?def process_item(self, item, spider):name = item.__class__.__name__self.db[name].insert(dict(item))return item ?def close_spider(self, spider):self.client.close()MongoPipeline 類實(shí)現(xiàn)了 API 定義的另外幾個(gè)方法。
-
from_crawler:這是一個(gè)類方法,用 @classmethod 標(biāo)識(shí),是一種依賴注入的方式,方法的參數(shù)就是 crawler,通過(guò) crawler 這個(gè)參數(shù)我們可以拿到全局配置的每個(gè)配置信息,在全局配置 settings.py 中我們可以定義 MONGO_URI 和 MONGO_DB 來(lái)指定 MongoDB 連接需要的地址和數(shù)據(jù)庫(kù)名稱,拿到配置信息之后返回類對(duì)象即可。所以這個(gè)方法的定義主要是用來(lái)獲取 settings.py 中的配置的。
-
open_spider:當(dāng) Spider 被開(kāi)啟時(shí),這個(gè)方法被調(diào)用。在這里主要進(jìn)行了一些初始化操作。
-
close_spider:當(dāng) Spider 被關(guān)閉時(shí),這個(gè)方法會(huì)調(diào)用,在這里將數(shù)據(jù)庫(kù)連接關(guān)閉。
最主要的 process_item 方法則執(zhí)行了數(shù)據(jù)插入操作。
定義好 TextPipeline 和 MongoPipeline 這兩個(gè)類后,我們需要在 settings.py 中使用它們。MongoDB 的連接信息還需要定義。
我們?cè)?settings.py 中加入如下內(nèi)容:
ITEM_PIPELINES = {'tutorial.pipelines.TextPipeline': 300,'tutorial.pipelines.MongoPipeline': 400, } MONGO_URI='localhost' MONGO_DB='tutorial'賦值 ITEM_PIPELINES 字典,鍵名是 Pipeline 的類名稱,鍵值是調(diào)用優(yōu)先級(jí),是一個(gè)數(shù)字,數(shù)字越小則對(duì)應(yīng)的 Pipeline 越先被調(diào)用。
再重新執(zhí)行爬取,命令如下所示:
scrapy crawl quotes爬取結(jié)束后,MongoDB 中創(chuàng)建了一個(gè) tutorial 的數(shù)據(jù)庫(kù)、QuoteItem 的表,如圖所示。
代碼
本節(jié)代碼地址:https://github.com/Python3WebSpider/ScrapyTutorial。
結(jié)語(yǔ)
我們通過(guò)抓取 Quotes 網(wǎng)站完成了整個(gè) Scrapy 的簡(jiǎn)單入門(mén)。但這只是冰山一角,還有很多內(nèi)容等待我們?nèi)ヌ剿鳌?/p>
總結(jié)
以上是生活随笔為你收集整理的第42讲:scrapy框架的基本使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 第43讲:灵活好用的 Spider 的用
- 下一篇: 第41讲:Scrapy框架的介绍