
來源:Python爬蟲與數(shù)據(jù)挖掘
作者:霖hero
大家好!我是霖hero。上個(gè)月的時(shí)候,我寫了一篇關(guān)于IP代理的文章,手把手教你使用XPath爬取免費(fèi)代理IP,今天在這里分享我的第二篇文章,希望大家可以喜歡。
有一天,我在逛街,突然被一聲靚仔打斷了我的腳步,回頭一看,原來是水果攤阿姨叫我買水果,說我那么靚仔,便宜一點(diǎn)買給我,自戀的我無法拒絕阿姨的一聲聲靚仔,于是買了很多水果回家,家人問我水果多少錢,結(jié)果如何,沒錯(cuò),水果買貴了!今天我們使用scrapy框架來爬取北京新發(fā)地價(jià)格行情,了解商品價(jià)格,家人再也不怕我買貴東西啦。
在爬取之前,我們先來學(xué)習(xí)一下什么Scrapy框架。
Scrapy是一個(gè)基于Twisted的異步處理框架,是純Python實(shí)現(xiàn)的爬蟲框架,是提取結(jié)構(gòu)性數(shù)據(jù)而編寫的應(yīng)用框架,其架構(gòu)清晰,模塊之間的耦合程度低,可擴(kuò)展性極強(qiáng),我們只需要少量的代碼就能夠快速抓取數(shù)據(jù)。
首先我們看看經(jīng)典的Scrapy框架架構(gòu)圖,如下圖所示:
學(xué)Scrapy框架的絕大部分都看過這個(gè)圖,圖中分了很多部分,接下來,我們通過下面的表來簡(jiǎn)單地了解各個(gè)部分的作用。
名稱 |
作用 |
是否要手寫代碼 |
Engine |
引擎,負(fù)責(zé)數(shù)據(jù)和信號(hào)的在不同模塊間的傳遞。 |
否 |
Scheduler |
調(diào)度器,存放引擎發(fā)過來的requests請(qǐng)求,在引擎再次請(qǐng)求的時(shí)候?qū)⒄?qǐng)求提供給引擎。 |
否 |
Downloader |
下載器,下載網(wǎng)頁響應(yīng)的內(nèi)容并將內(nèi)容返回給引擎。 |
否 |
Spiders |
爬蟲,處理引擎?zhèn)鬟^來的網(wǎng)頁內(nèi)容并提取數(shù)據(jù)、url,并返回給引擎。 |
是 |
Item Pipeline |
管道,處理引擎?zhèn)鬟^來的數(shù)據(jù),主要任務(wù)是清洗、驗(yàn)證和存儲(chǔ)數(shù)據(jù)。 |
是 |
Downloader Middlewares |
下載器中間件,位于引擎和下載器之間的橋梁框架,主要是處理引擎與下載器之間的請(qǐng)求及響應(yīng),可以自定義下載擴(kuò)展,如設(shè)置代理。 |
一般不用手寫 |
Spider MiddlewaresSpider |
中間件,位于引擎和爬蟲之間的橋梁框架,主要處理向爬蟲輸入的響應(yīng)和輸出的結(jié)果及新的請(qǐng)求。 |
一般不用手寫 |
在表中,我們可以發(fā)現(xiàn),每部分都要經(jīng)過引擎,上圖中Scrapy Engine部分也是放在正中心,由此可知,Engine引擎是整個(gè)框架的核心。
注意:這些模塊部分只有Spiders和Item Pipeline需要我們自己手寫代碼,其他的大部分都不需要。
大致了解了Scrapy框架的各個(gè)部分后,接下來我們開始創(chuàng)建一個(gè)Scrapy項(xiàng)目,可以使用如下命令:
scrapy startproject <Scrapy項(xiàng)目名>
創(chuàng)建一個(gè)scrapy項(xiàng)目名為test1的項(xiàng)目,如下圖所示:
這樣我們就創(chuàng)建好Scrapy項(xiàng)目了,如下圖所示:
其中:
要?jiǎng)?chuàng)建Spider爬蟲,首先我們要進(jìn)入剛才創(chuàng)建的Scrapy目錄中,再在命令行運(yùn)行以下命令:
scrapy genspider <爬蟲名字> <允許爬取的域名>
以
http://quotes.toscrape.com
網(wǎng)站為例子,該網(wǎng)站是一個(gè)著名作家名言的網(wǎng)站,創(chuàng)建Spider爬蟲如下圖所示:
創(chuàng)建spider爬蟲后,spiders文件夾中多了一個(gè)firstspider.py,這個(gè)py文件就是我們創(chuàng)建爬蟲,文件內(nèi)容如下所示:
import scrapy class FirstspiderSpider(scrapy.Spider): name = 'firstSpider' allowed_domains = ['quotes.toscrape.com']
start_urls = ['http://quotes.toscrape.com/'] def parse(self, response): pass
其中:
大致了解了firstspider.py文件內(nèi)容后,我們接下來嘗試在parse()方法中提取響應(yīng)的數(shù)據(jù),具體代碼如下所示:
xpath_parse = response.xpath('/html/body/div[1]/div[2]/div[1]/div') for xpath in xpath_parse:
item={}
item['text'] = xpath.xpath('./span[1]/text()').extract_first().replace('“','').replace('”','') item['author']=xpath.xpath('./span[2]/small/text()').extract_first() print(item)
這樣我們就成功提取到引擎響應(yīng)的內(nèi)容數(shù)據(jù)了,接著輸入以下命令來運(yùn)行spider爬蟲:
scrapy crawl firstSpider
運(yùn)行結(jié)果如下:
運(yùn)行后發(fā)現(xiàn)我們結(jié)果里面多了很多l(xiāng)og日志,這時(shí)可以通過在settings.py添加以下代碼,就可以屏蔽這些log日志:
LOG_LEVEL="WARNING"
這樣就可以直接輸入我們想要的內(nèi)容,如下圖所示:
有人可能問:那User-Agent在哪里設(shè)置?
我們可以在settings.py中設(shè)置User-Agent,代碼如下所示:
為了避免拼寫錯(cuò)誤或者定義字段錯(cuò)誤,我們可以在items.py文件中定義好字段,在上面提取數(shù)據(jù)中,我們獲取了text、author內(nèi)容,所以我們可以在items.py定義text和author字段,具體代碼如下所示:
import scrapy class Test1Item(scrapy.Item): text= scrapy.Field() author = scrapy.Field()
在items.py文件中,我們只需要使用scrapy.Field()來進(jìn)行定義即可,scrapy.Field()是一個(gè)字典,總的來說我們可以把該類理解為一個(gè)字典。
接著在firstspider.py文件中導(dǎo)入我們的items.py,以及修改item={},如下所示:
from test1.items import Test1Item
item=Test1Item()
有人可能會(huì)說為什么要多此一舉定義一個(gè)字典呢?
當(dāng)我們?cè)讷@取到數(shù)據(jù)的時(shí)候,使用不同的item來存放不同的數(shù)據(jù),在把數(shù)據(jù)交給pipeline的時(shí)候,可以通過isinstance(item,Test1Item)來判斷數(shù)據(jù)屬于哪個(gè)item,進(jìn)行不同的數(shù)據(jù)(item)處理。
例如我們獲取到京東、淘寶、拼多多的數(shù)據(jù)時(shí),我們可以items.py文件中定義好對(duì)應(yīng)的字段,具體代碼如下:
import scrapy class jingdongItem(scrapy.Item): text= scrapy.Field() author = scrapy.Field() class taobaoItem(scrapy.Item): text= scrapy.Field() author = scrapy.Field() class pddItem(scrapy.Item): text= scrapy.Field() author = scrapy.Field()
定義好字段后,這是我們通過在pipeline.py文件中編寫代碼,對(duì)不同的item數(shù)據(jù)進(jìn)行區(qū)分,具體代碼如下:
from test1.items import jingdongItem class Test1Pipeline: def process_item(self, item, spider): if isinstance(item,jingdongItem):
print(item)
首先我們通過導(dǎo)入我們的items.py,通過isinstance()函數(shù)來就可以成功獲取到對(duì)應(yīng)的item數(shù)據(jù)了。
Item Pipeline為項(xiàng)目管道,當(dāng)Item生成后,它就會(huì)自動(dòng)被送到Item Pipeline進(jìn)行處理,我們常用Item Pipeline來做以下操作:
pipelines.py內(nèi)容如下所示:
from itemadapter import ItemAdapter class Test1Pipeline: def process_item(self, item, spider): return item
在process_item()方法中,傳入了兩個(gè)參數(shù),一個(gè)參數(shù)是item,每次Spider生成的Item都會(huì)作為參數(shù)傳遞過來。另一個(gè)參數(shù)是spider,就是Spider的示例。
完成pipeline代碼后,需要在setting.py中設(shè)置開啟,開啟方式很簡(jiǎn)單,只要把setting.py內(nèi)容中的以下代碼的注釋取消即可:
ITEM_PIPELINES = { 'test1.pipelines.Test1Pipeline': 300, }
其中:
注意:
當(dāng)我們有多個(gè)spider爬蟲時(shí),為了滿足不同的spider爬蟲需求,這時(shí)可以定義不同的pipeline處理不同的item內(nèi)容;
當(dāng)一個(gè)spider的內(nèi)容可能要做不同的操作時(shí),例如存入不同的數(shù)據(jù)庫(kù)中,這時(shí)可以定義不同的pipeline處理不同的item操作。
例如當(dāng)我們有多個(gè)spider爬蟲時(shí),可以通過pipeline.py編寫代碼定義多個(gè)pipeline,具體代碼如下:
class jingdongPipeline1: def process_item(self, item, spider): if spider.name=="jingdong":
print(item) return item class taobaoPipeline: def process_item(self, item, spider): if spider.name=="taobao":
print(item) return item
這樣我們就可以處理到對(duì)應(yīng)的spider爬蟲傳遞過來的數(shù)據(jù)了。
定義好pipeline后,我們要在settings.py中設(shè)置pipeline權(quán)重,也就是那個(gè)pipeline先運(yùn)行,具體代碼如下:
ITEM_PIPELINES = { 'test1.pipelines.jingdongPipeline': 300, 'test1.pipelines.taobaoPipeline': 301, }
在上面我們已經(jīng)提取到想要的數(shù)據(jù),接下來將數(shù)據(jù)傳到pipeline中,傳輸很簡(jiǎn)單,我們只需要使用yield,代碼如下:
yield item
沒錯(cuò),只要在spider爬蟲中寫入這一行代碼即可,那么為什么要使用yield呢?,我用return不能行嗎?
行,但yield是讓整個(gè)函數(shù)變成一個(gè)生成器,每次遍歷的時(shí)候挨個(gè)讀到內(nèi)存中,這樣不會(huì)導(dǎo)致內(nèi)存的占用量瞬間變高。
我們成功獲取到了一頁數(shù)據(jù)了,那么問題來了,如何實(shí)現(xiàn)翻頁呢,方法有很多種,我們主要介紹兩種。
我們通過在spider爬蟲中,也就是我們創(chuàng)建的firstspider.py中添加以下代碼,具體代碼如下:
def start_requests(self): for i in range(1,3):
url=f'https://quotes.toscrape.com/page/{i}/' yield scrapy.Request(url=url,callback=self.parse)
我們可以通過parse()方法中實(shí)現(xiàn)翻頁,具體代碼如下:
for i in range(2,3):
url = f'https://quotes.toscrape.com/page/{i}/' yield scrapy.Request(url=url,callback=self.parse)
大家可以發(fā)現(xiàn),上面兩種翻頁方式都差不多,只是一個(gè)在start_requests()方法實(shí)現(xiàn),一個(gè)在parse()方法實(shí)現(xiàn)。
但都要使用scrapy.Request()方法,該方法能構(gòu)建一個(gè)requests,同時(shí)指定提取數(shù)據(jù)的callback函數(shù)
scrapy.Requeset(url,callback,method='GET',headers,cookies,meta,dont_filter=False)
其中:
我們已經(jīng)獲取到數(shù)據(jù)而且實(shí)現(xiàn)了翻頁,接下來是保存數(shù)據(jù)。
保存在文件中
當(dāng)我們要把數(shù)據(jù)保存成文件的時(shí)候,不需要任何額外的代碼,只要執(zhí)行如下代碼即可:
scrapy crawl spider爬蟲名 -o xxx.json #保存為JSON文件 scrapy crawl spider爬蟲名 -o xxx.jl或jsonlines #每個(gè)Item輸出一行json scrapy crawl spider爬蟲名 -o xxx.csv #保存為csv文件 scrapy crawl spider爬蟲名 -o xxx.xml #保存為xml文件
想要保存為什么格式的文件,只要修改后綴就可以了,在這里我就不一一例舉了。
保存MongoDB中
當(dāng)我們要把數(shù)據(jù)保存在MongoDB數(shù)據(jù)庫(kù)的時(shí)候,就要使用Item Pipeline模塊了,也就是說要在pipeline.py中編寫代碼,具體代碼如下所示:
from pymongo import MongoClient
client=MongoClient()
collection=client["test1"]["firstspider"]
class Test1Pipeline: def process_item(self, item, spider): collection.insert(item) return item
首先我們導(dǎo)入MongoClient模塊并實(shí)例化MongoClient,創(chuàng)建一個(gè)集合,然后在process_item()方法中使用insert()方法把數(shù)據(jù)插入MongoDB數(shù)據(jù)庫(kù)中。
好了,Scrapy知識(shí)就講到這里,下一篇文章小編將帶大家爬取北京新發(fā)地價(jià)格行情,順便鞏固我們今天學(xué)的知識(shí)。
大家好,我是霖hero。這篇文章主要給大家分享了Scrapy框架的條條框框,Scrapy是一個(gè)基于Twisted的異步處理框架,是純Python實(shí)現(xiàn)的爬蟲框架,是提取結(jié)構(gòu)性數(shù)據(jù)而編寫的應(yīng)用框架,其架構(gòu)清晰,模塊之間的耦合程度低,可擴(kuò)展性極強(qiáng)。
數(shù)據(jù)分析咨詢請(qǐng)掃描二維碼
若不方便掃碼,搜微信號(hào):CDAshujufenxi
LSTM 模型輸入長(zhǎng)度選擇技巧:提升序列建模效能的關(guān)鍵? 在循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)家族中,長(zhǎng)短期記憶網(wǎng)絡(luò)(LSTM)憑借其解決長(zhǎng)序列 ...
2025-07-11CDA 數(shù)據(jù)分析師報(bào)考條件詳解與準(zhǔn)備指南? ? 在數(shù)據(jù)驅(qū)動(dòng)決策的時(shí)代浪潮下,CDA 數(shù)據(jù)分析師認(rèn)證愈發(fā)受到矚目,成為眾多有志投身數(shù) ...
2025-07-11數(shù)據(jù)透視表中兩列相乘合計(jì)的實(shí)用指南? 在數(shù)據(jù)分析的日常工作中,數(shù)據(jù)透視表憑借其強(qiáng)大的數(shù)據(jù)匯總和分析功能,成為了 Excel 用戶 ...
2025-07-11尊敬的考生: 您好! 我們誠(chéng)摯通知您,CDA Level I和 Level II考試大綱將于 2025年7月25日 實(shí)施重大更新。 此次更新旨在確保認(rèn) ...
2025-07-10BI 大數(shù)據(jù)分析師:連接數(shù)據(jù)與業(yè)務(wù)的價(jià)值轉(zhuǎn)化者? ? 在大數(shù)據(jù)與商業(yè)智能(Business Intelligence,簡(jiǎn)稱 BI)深度融合的時(shí)代,BI ...
2025-07-10SQL 在預(yù)測(cè)分析中的應(yīng)用:從數(shù)據(jù)查詢到趨勢(shì)預(yù)判? ? 在數(shù)據(jù)驅(qū)動(dòng)決策的時(shí)代,預(yù)測(cè)分析作為挖掘數(shù)據(jù)潛在價(jià)值的核心手段,正被廣泛 ...
2025-07-10數(shù)據(jù)查詢結(jié)束后:分析師的收尾工作與價(jià)值深化? ? 在數(shù)據(jù)分析的全流程中,“query end”(查詢結(jié)束)并非工作的終點(diǎn),而是將數(shù) ...
2025-07-10CDA 數(shù)據(jù)分析師考試:從報(bào)考到取證的全攻略? 在數(shù)字經(jīng)濟(jì)蓬勃發(fā)展的今天,數(shù)據(jù)分析師已成為各行業(yè)爭(zhēng)搶的核心人才,而 CDA(Certi ...
2025-07-09【CDA干貨】單樣本趨勢(shì)性檢驗(yàn):捕捉數(shù)據(jù)背后的時(shí)間軌跡? 在數(shù)據(jù)分析的版圖中,單樣本趨勢(shì)性檢驗(yàn)如同一位耐心的偵探,專注于從單 ...
2025-07-09year_month數(shù)據(jù)類型:時(shí)間維度的精準(zhǔn)切片? ? 在數(shù)據(jù)的世界里,時(shí)間是最不可或缺的維度之一,而year_month數(shù)據(jù)類型就像一把精準(zhǔn) ...
2025-07-09CDA 備考干貨:Python 在數(shù)據(jù)分析中的核心應(yīng)用與實(shí)戰(zhàn)技巧? ? 在 CDA 數(shù)據(jù)分析師認(rèn)證考試中,Python 作為數(shù)據(jù)處理與分析的核心 ...
2025-07-08SPSS 中的 Mann-Kendall 檢驗(yàn):數(shù)據(jù)趨勢(shì)與突變分析的有力工具? ? ? 在數(shù)據(jù)分析的廣袤領(lǐng)域中,準(zhǔn)確捕捉數(shù)據(jù)的趨勢(shì)變化以及識(shí)別 ...
2025-07-08備戰(zhàn) CDA 數(shù)據(jù)分析師考試:需要多久?如何規(guī)劃? CDA(Certified Data Analyst)數(shù)據(jù)分析師認(rèn)證作為國(guó)內(nèi)權(quán)威的數(shù)據(jù)分析能力認(rèn)證 ...
2025-07-08LSTM 輸出不確定的成因、影響與應(yīng)對(duì)策略? 長(zhǎng)短期記憶網(wǎng)絡(luò)(LSTM)作為循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)的一種變體,憑借獨(dú)特的門控機(jī)制,在 ...
2025-07-07統(tǒng)計(jì)學(xué)方法在市場(chǎng)調(diào)研數(shù)據(jù)中的深度應(yīng)用? 市場(chǎng)調(diào)研是企業(yè)洞察市場(chǎng)動(dòng)態(tài)、了解消費(fèi)者需求的重要途徑,而統(tǒng)計(jì)學(xué)方法則是市場(chǎng)調(diào)研數(shù) ...
2025-07-07CDA數(shù)據(jù)分析師證書考試全攻略? 在數(shù)字化浪潮席卷全球的當(dāng)下,數(shù)據(jù)已成為企業(yè)決策、行業(yè)發(fā)展的核心驅(qū)動(dòng)力,數(shù)據(jù)分析師也因此成為 ...
2025-07-07剖析 CDA 數(shù)據(jù)分析師考試題型:解鎖高效備考與答題策略? CDA(Certified Data Analyst)數(shù)據(jù)分析師考試作為衡量數(shù)據(jù)專業(yè)能力的 ...
2025-07-04SQL Server 字符串截取轉(zhuǎn)日期:解鎖數(shù)據(jù)處理的關(guān)鍵技能? 在數(shù)據(jù)處理與分析工作中,數(shù)據(jù)格式的規(guī)范性是保證后續(xù)分析準(zhǔn)確性的基礎(chǔ) ...
2025-07-04CDA 數(shù)據(jù)分析師視角:從數(shù)據(jù)迷霧中探尋商業(yè)真相? 在數(shù)字化浪潮席卷全球的今天,數(shù)據(jù)已成為企業(yè)決策的核心驅(qū)動(dòng)力,CDA(Certifie ...
2025-07-04CDA 數(shù)據(jù)分析師:開啟數(shù)據(jù)職業(yè)發(fā)展新征程? ? 在數(shù)據(jù)成為核心生產(chǎn)要素的今天,數(shù)據(jù)分析師的職業(yè)價(jià)值愈發(fā)凸顯。CDA(Certified D ...
2025-07-03