版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲Python網(wǎng)絡爬蟲技術案例教程PythonWangluoPachongJishuAnliJiaochengCOMMITTEDCOMMITTEDCOMMITTECOMMITTECONTENTS目錄COMMITTED第1章網(wǎng)絡爬蟲入門
第2章爬蟲基礎第3章網(wǎng)頁解析基礎第4章爬取動態(tài)加載數(shù)據(jù)第5章反爬蟲策略第6章模擬登錄和處理驗證碼
第7章爬取App和PC客戶端第8章爬蟲框架Scrapy第9章分布式爬蟲第10章項目實戰(zhàn)COMMITTEDCOMMITTEDCOMMITTECOMMITTECOMMITTED掃碼下載文旌課堂APP掃碼簽到(202X.XX.XXXX:XX至202X.XX.XXXX:XX)簽到方式教師通過“文旌課堂APP”生成簽到二維碼,并設置簽到時間,學生通過“文旌課堂APP”掃描“簽到二維碼”進行簽到。簽到.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲第8章爬蟲框架Scrapy本章導讀雖然利用前面所學知識也可以實現(xiàn)爬蟲的全部流程,但是當遇到需要爬取的網(wǎng)頁較多、數(shù)據(jù)量較大時,使用框架可以讓爬蟲程序更強大、更高效。本章從網(wǎng)絡爬蟲框架Scrapy的構成入手,介紹Scrapy的應用方法,包括如何創(chuàng)建項目、修改items腳本、創(chuàng)建spider腳本、修改settings腳本、運行爬蟲程序、修改pipelines腳本和定制Middleware等內容。學習目標理解Scrapy框架的構成。掌握使用Scrapy框架創(chuàng)建爬蟲程序獲取所需數(shù)據(jù)的方法。能使用Scrapy框架編寫爬蟲程序爬取網(wǎng)站數(shù)據(jù)。8.1Scrapy框架8.2Scrapy應用第8章爬蟲框架Scrapy.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲SectionTitle8.1Scrapy框架8.1Scrapy框架Scrapy是目前Python中使用最廣泛的爬蟲框架,用于爬取網(wǎng)站數(shù)據(jù),提取結構性的數(shù)據(jù)。簡單來說,Scrapy是一個半成品,相關擴展組件多,可配置和可擴展程度非常高,可以幫助用戶簡單快速地實現(xiàn)一個網(wǎng)絡爬蟲。Scrapy框架由7個組件構成,如圖8-1所示。圖8-1Scrapy框架Engine(引擎)負責處理系統(tǒng)的數(shù)據(jù)流、觸發(fā)事務,是整個框架的核心。Scheduler(調度器)負責處理所有的Request,并按照一定的方式將其進行整理、排列和入隊。此外,Scheduler可以自動去除重復的URL,如果特定Request的URL不需要去重也可以通過設置實現(xiàn),如POST請求。Downloader(下載器)負責下載網(wǎng)頁內容。8.1Scrapy框架Spider負責解析所有的Response,提取Item所需的數(shù)據(jù)和新的URL。用戶可以在一個項目中編寫多個Spider,每個負責處理一個特定(或一些)網(wǎng)站。ItemPipeline(項目管道)負責處理Item,常見的處理有清理、驗證和存儲數(shù)據(jù)等。DownloaderMiddleware(下載中間件)位于Engine和Downloader之間,可以自定義擴展下載功能,如自動更換User-Angent、設置代理IP等。SpiderMiddleware(Spider中間件)位于Engine和Spider之間,可以自定義擴展Engine和Spider間通信的功能。8.1Scrapy框架Item是保存爬取數(shù)據(jù)的容器,其使用方式和字典類似,并且提供額外保護機制來避免拼寫錯誤導致的未定義字段錯誤。8.1Scrapy框架在Scrapy中由Engine控制數(shù)據(jù)流,其工作的基本步驟如下。(1)Engine從Spider獲取初始爬取列表的Request。(2)Engine將要爬取的Request發(fā)送給Scheduler,通過Scheduler進行調度。(3)Engine向Scheduler獲取下一個要爬取的Request。(4)Engine將Request通過DownloaderMiddleware發(fā)送給Downloader。(5)當網(wǎng)頁下載完畢,Downloader生成該網(wǎng)頁的Response,并將其通過DownloaderMiddleware提交給Engine。8.1Scrapy框架(6)Engine將接收到Response通過SpiderMiddleware發(fā)送給Spider處理。(7)Spider解析響應,提取Item所需的數(shù)據(jù)和新的URL,并將Item和新的Request通過SpiderMiddleware提交給Engine。(8)Engine將Item發(fā)送給ItemPipeline,將新的Request發(fā)送給Scheduler。(9)重復第(2)~(8)步,直到Scheduler中沒有Request,Engine關閉該爬蟲程序,爬取結束。8.1Scrapy框架.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲SectionTitle8.2Scrapy應用Python提供scrapy庫實現(xiàn)Scrapy爬蟲框架,scrapy庫不是Python內置的標準庫,使用之前需要安裝,安裝方法與requests庫的安裝類似(請參考2.3.2節(jié)),此處不再贅述。本節(jié)以創(chuàng)建BaiduSpider項目為例,介紹使用Scrapy框架編寫爬蟲程序的過程。Scrapy應用8.2Scrapy應用8.2.1創(chuàng)建項目scrapy庫提供了startproject命令用于創(chuàng)建一個爬蟲項目,其語法格式如下:scrapystartproject<project_name>[project_dir]8.2Scrapy應用(1)project_name:表示創(chuàng)建的爬蟲項目名稱。(2)project_dir:表示存放爬蟲項目的路徑。指定該參數(shù)后,會在project_dir目錄下生成一個名為project_name的文件夾;如果不指定該參數(shù),則將在命令執(zhí)行路徑下生成。Scrapy的命令須通過命令行運行,在PyCharm中,可以通過Terminal窗口來運行。例如,在“D:\PycharmProjects\第8章”下,創(chuàng)建一個名為“BaiduSpider”的爬蟲項目,其過程為:啟動Pycharm,在界面的下方單擊“Terminal”按鈕,然后在打開的Terminal窗口中切換至“D:\PycharmProjects\第8章”,輸入“scrapystartprojectBaiduSpider”命令并運行,如圖8-2所示。8.2Scrapy應用圖8-2創(chuàng)建“BaiduSpider”爬蟲項目8.2Scrapy應用創(chuàng)建項目后,在“D:\PycharmProjects\第8章”下會生成一個名為“BaiduSpider”的文件夾,其目錄結構見圖8-2。其中每個文件的功能如表8-1所示。8.2Scrapy應用文件說明spiders創(chuàng)建Scrapy項目后自動創(chuàng)建的一個文件夾,用于存放用戶編寫的spider腳本,每一個腳本都是一個文件__init__.py空文件,將其上級目錄變成一個模塊items.py定義Item中數(shù)據(jù)的結構,可以包含多個Itemmiddlewares.py根據(jù)需求定義DownloaderMiddleware和SpiderMiddleware,可以包含多個Middlewarepipelines.py根據(jù)需求定義Pipeline,可以包含多個Pipelinesettings.py定義項目的全局變量scrapy.cfgScrapy項目的配置文件,定義項目的配置文件路徑、部署相關信息等表8-1Scrapy爬蟲項目的文件功能8.2.2修改items腳本scrapy庫提供Item對象來實現(xiàn)將爬取到的數(shù)據(jù)轉換成結構化數(shù)據(jù)的功能。實現(xiàn)方法是定義Item類(繼承scrapy.Item類),并定義類中的數(shù)據(jù)類型為scrapy.Filed字段。BaiduSpider項目中items腳本的模板如圖8-3所示。圖8-3items腳本模板8.2Scrapy應用BaiduSpider項目爬取的目標是百度首頁熱榜新聞,包括排名、標題、鏈接和搜索結果個數(shù)。根據(jù)項目目標,重新定義Item,在items.py中添加如下代碼。classNewsItem(scrapy.Item): #定義NewsItem類index=scrapy.Field() #定義排名title=scrapy.Field() #定義標題link=scrapy.Field() #定義鏈接newsNum=scrapy.Field() #定義搜索結果個數(shù)8.2Scrapy應用8.2.3創(chuàng)建spider腳本scrapy庫提供了genspider命令用于創(chuàng)建一個spider腳本,其語法格式如下:scrapygenspider[template]<name><domain>8.2Scrapy應用(1)template:表示創(chuàng)建模板的類型,缺省則使用默認模板。(2)name:表示創(chuàng)建的spider腳本名稱,創(chuàng)建后會在spiders目錄下生成一個以name命名的.py文件。(3)domain:表示要爬取網(wǎng)站的域名。在BaiduSpider項目中創(chuàng)建一個爬取百度首頁熱榜新聞的spider腳本,命名為news,域名為,其過程為:輸入“cdBaiduSpider”命令并運行,切換到“BaiduSpider”目錄下;然后輸入“scrapygenspidernews”命令并運行,創(chuàng)建一個spider腳本,如圖8-4所示。8.2Scrapy應用創(chuàng)建spider腳本后,在spiders目錄下生成了一個名為“news.py”的文件,其模板見圖8-4。在該文件中定義了一個NewsSpider類,其中包含三個屬性和一個方法,它們的說明如下。(1)name:在同一個項目中,名字是唯一的,用來區(qū)分不同的spider。(2)allowed_domains:允許爬取的域名,如果初始或后續(xù)請求的URL不是這個域名下的,則請求會被過濾掉,可以根據(jù)需要編輯或添加。(3)start_urls:spider初始爬取的URL列表,可以根據(jù)需要編輯或添加。(4)parse(self,response):解析返回的響應,提取數(shù)據(jù)或新的URL,response是請求start_urls后返回的響應。8.2Scrapy應用由于scrapy庫支持CSS選擇器、XPath選擇器和正則表達式,所以解析響應時可以調用xpath()、css()等方法提取數(shù)據(jù)。調用方法后返回的數(shù)據(jù)是SelectorList類型,并不是真正的文本內容。此時,可以使用extract()方法(返回列表)或extract_first()方法(返回列表的第一個元素)來提取所需數(shù)據(jù)。如果想要請求新的URL,Scrapy可以調用Request()方法來實現(xiàn),其語法格式如下:其中常用的參數(shù)及說明如表8-2所示。Request(url,callback,method=’GET’,headers,body,cookies,meta,encoding=’utf-8’,priority=0,dont_filyer=False,errback,flags)8.2Scrapy應用圖8-4創(chuàng)建spider腳本8.2Scrapy應用表8-2Request方法常用的參數(shù)及說明參數(shù)說明url接收str,表示請求的網(wǎng)址,無默認值callback接收同一個類中的方法,表示回調的方法,解析該請求返回的響應,未指定則繼續(xù)調用parse方法,無默認值method接收str,表示請求的方法,默認為“GET”headers接收str、dict和list,表示請求頭,無默認值cookies接收list和dict,表示請求的cookies,無默認值meta接收dict,表示Request.meta屬性的初始值,如果指定了該參數(shù),dict將會淺拷貝,無默認值8.2Scrapy應用在BaiduSpider項目中,實現(xiàn)news爬蟲的過程如下。(1)在parse()方法中提取百度首頁熱榜新聞的排名、標題和鏈接,并寫入NewsItem類的對象中;然后調用Scrapy.Request()方法請求新的鏈接,并使用callback參數(shù)指定回調方法為parse_newsnum,使用meta參數(shù)在兩個解析方法之間傳遞NewsItem類的對象。(2)定義parse_newsnum()方法,解析請求新的鏈接返回的響應,提取每條新聞的搜索結果數(shù),并寫入NewsItem類的對象中。news.py修改后的代碼如下。importscrapy #導入scrapy模塊#導入items模塊中的NewsItem類8.2Scrapy應用fromBaiduSpider.itemsimportNewsItemfromcopyimportdeepcopy #導入deepcopy模塊classNewsSpider(scrapy.Spider): #定義NewsSpider類name='news' #初始化name#初始化allowed_domainsallowed_domains=['']start_urls=['/'] #初始化start_urlsdefparse(self,response): #定義parse方法#查找ul節(jié)點下的所有l(wèi)i節(jié)點news_list=response.xpath(8.2Scrapy應用'//ul[@class="s-hotsearch-content"]/li')fornewsinnews_list: #遍歷li節(jié)點item=NewsItem() #初始化對象item#查找排名節(jié)點,獲取文本,并賦值給item中的indexitem['index']=news.xpath('a/span[1]/text()').extract_first()#查找標題節(jié)點,獲取文本,并賦值給item中的titleitem['title']=news.xpath('a/span[2]/text()').extract_first()#查找鏈接節(jié)點,獲取文本,并賦值給item中的link8.2Scrapy應用item['link']=news.xpath('a/@href').extract_first()#發(fā)送請求,并指定回調方法為parse_newsnumyieldscrapy.Request(item['link'],callback=self.parse_newsnum,meta={'item':deepcopy(item)})defparse_newsnum(self,response): #定義parse_newsnum方法item=response.meta['item'] #傳遞item8.2Scrapy應用#查找搜索結果個數(shù)節(jié)點,獲取文本,并賦值給item中的newsNumitem['newsNum']=response.xpath('//span[@class="nums_text"]/text()').extract_first()yielditem #返回item8.2Scrapy應用scrapy.Request()方法中使用meta參數(shù)在兩個解析方法之間傳遞Item時,避免Item數(shù)據(jù)發(fā)生錯誤,須使用深拷貝,如meta={'item':deepcopy(item)},而且需要導入deepcopy模塊。導入items模塊中的NewsItem類時,需要設置路徑。方法為:右擊項目名(如BaiduSpider),在彈出的快捷菜單中選擇“MarkDirectoryas”→“SourcesRoot”選項即可,如圖8-5所示。8.2Scrapy應用圖8-5設置導入類路徑8.2Scrapy應用Scrapy還提供FormRequest()方法發(fā)送請求并使用表單提交數(shù)據(jù),如POST請求。常用的參數(shù)有url、callback、method、formdata、meta和dont_filter等。其中,formdata為字典類型,表示表單提交的數(shù)據(jù);dont_filter為bool類型,如果需要多次提交表單,且url一樣,那么必須將其設置為True,以防止被當成重復請求被過濾。8.2Scrapy應用8.2.4修改settings腳本settings腳本提供鍵值映射的全局命名空間,可以使用代碼提取其中的配置值。默認的settings文件中共有25項設置,每項設置的說明如表8-3所示。設置名稱說明BOT_NAMEScrapy項目的名稱,用來構造默認的User-Agent,也用于日志記錄,默認為創(chuàng)建項目時的項目名稱SPIDER_MODULESScrapy使用的spiders列表,默認為spiders目錄NEWSPIDER_MODULE使用genspider命令創(chuàng)建新的spider的目錄,默認為spiders目錄,僅接收str表8-3settings文件每項設置說明8.2Scrapy應用設置名稱說明USER_AGENT設置請求頭中的User-AgentROBOTSTXT_OBEY是否遵守Robots協(xié)議,默認為TrueCONCURRENT_REQUESTSDownloader執(zhí)行并發(fā)請求的最大數(shù)量,默認為16DOWNLOAD_DELAYDownloader下載同一網(wǎng)站的連續(xù)網(wǎng)頁之前等待的時間,主要用于限制spider的速度,默認為3sCONCURRENT_REQUESTS_PER_DOMAIN單個網(wǎng)站執(zhí)行并發(fā)請求的最大數(shù)量,默認為16CONCURRENT_REQUESTS_PER_IP單個IP執(zhí)行并發(fā)請求的最大數(shù)量,如果非零,則忽略CONCURRENT_REQUESTS_PER_DOMAIN的設置,改為使用此設置,表示并發(fā)限制將應用于每個IP,而不是每個網(wǎng)站TELNETCONSOLE_ENABLED是否啟用telnet控制臺,默認為TrueDEFAULT_REQUEST_HEADERS設置HTTP請求頭SPIDER_MIDDLEWARES啟用的Spider中間件及調用順序,為字典形式(續(xù)表)8.2Scrapy應用設置名稱說明DOWNLOADER_MIDDLEWARES啟用的Downloader中間件及調用順序,為字典形式EXTENSIONS啟用的擴展名及調用順序,為字典形式ITEM_PIPELINES啟用的項目管道及調用順序,為字典形式AUTOTHROTTLE_ENABLED是否啟用AutoThrottle擴展,默認為FalseAUTOTHROTTLE_START_DELAY初始下載延遲,以秒為單位,默認為5sAUTOTHROTTLE_MAX_DELAY在高延遲情況下設置的最大下載延遲,以秒為單位,默認為60sAUTOTHROTTLE_TARGET_CONCURRENCY平行發(fā)送到遠程網(wǎng)站的平均請求數(shù)量,默認為1AUTOTHROTTLE_DEBUG是否啟用AutoThrottle調試模式,啟用時顯示收到的每個響應的統(tǒng)計數(shù)據(jù),以便用戶實時調整參數(shù),默認為FalseHTTPCACHE_ENABLED是否啟用HTTP緩存,默認為False(續(xù)表)8.2Scrapy應用設置名稱說明HTTPCACHE_EXPIRATION_SECS緩存請求的到期時間,以秒為單位,默認為0HTTPCACHE_DIR用于存儲HTTP緩存的目錄,如果為空,則HTTP緩存將被禁用,提供的是基于Scrapy目錄的相對路徑HTTPCACHE_IGNORE_HTTP_CODES禁用緩存列表中的HTTP代碼響應HTTPCACHE_STORAGE實現(xiàn)高速緩存存儲后端的類(續(xù)表)8.2Scrapy應用在BaiduSpider項目中,需要設置請求頭中的User-Agent和不遵守Robots協(xié)議,setting.py修改后的代碼如下。USER_AGENT='Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/83.0.4103.97Safari/537.36' #設置USER_AGENTROBOTSTXT_OBEY=False #設置不遵守Robots協(xié)議8.2Scrapy應用8.2.5運行爬蟲程序此時,BaiduSpider項目已經(jīng)基本完成,可以使用Scrapy中的crawl命令運行該項目,其語法格式如下:其中,“spider_name”參數(shù)表示spider腳本的名稱。在BaiduSpider目錄下,輸入“scrapycrawlnews”命令并運行,運行結果如圖8-6所示。scrapycrawl<spider_name>8.2Scrapy應用圖8-6news爬蟲運行的結果(部分)8.2Scrapy應用另外,還可以通過命令將爬取到的內容保存到文件中。例如,輸入“scrapycrawlnews-onews.json”命令并運行,即可將Item的內容保存到JSON文件中,保存的文件內容如圖8-7所示。圖8-7JSON文件保存的內容8.2Scrapy應用使用-o輸出JSON文件時,會默認使用unicode編碼,當內容為中文時,輸出的JSON文件不便于查看。此時,可以在settings.py文件中修改默認的編碼方式,即增加設置FEED_EXPORT_ENCODING='utf-8'。8.2Scrapy應用8.2.6修改pipelines腳本如果想進行更復雜的處理,如篩選一些有用的數(shù)據(jù)或將數(shù)據(jù)保存到數(shù)據(jù)庫中,則可以在pipelines腳本中通過定義ItemPipeline來實現(xiàn)。pipelines的腳本模板如圖8-8所示。圖8-8pipelines腳本模板8.2Scrapy應用定義ItemPipeline只需要定義一個類并實現(xiàn)process_item()方法即可。process_item()方法有兩個參數(shù):一個是item參數(shù),Spider生成的Item每次都會作為參數(shù)傳遞過來;另一個是spider參數(shù),它是Spider的實例(如果創(chuàng)建多個Spider,可以通過來區(qū)分)。該方法必須返回包含數(shù)據(jù)的字典或Item對象,或拋出DropItem異常并刪除該Item。在BaiduSpider項目中,定義一個TextPipeline類,實現(xiàn)將“index”為3的Item刪除。在pipelines.py中添加的代碼如下。8.2Scrapy應用#導入DropItem模塊fromscrapy.exceptionsimportDropItemclassTextPipeline: #定義TextPipeline類#定義process_item方法defprocess_item(self,item,spider):ifitem['index']=='3': #如果item中“index”為“3”raiseDropItem() #刪除itemelse: #如果item中“index”不為“3”returnitem #返回item8.2Scrapy應用另外,還定義了一個MongoPipeline類,實現(xiàn)將處理后的item存儲至MongoDB數(shù)據(jù)庫中。在pipelines.py中添加的代碼如下。importpymongo #導入pymongo模塊classMongoPipeline: #定義MongoPipeline類#定義__init__方法def__init__(self,mongo_uri,mongo_db):self.mongo_uri=mongo_uri #初始化類中的mongo_uriself.mongo_db=mongo_db #初始化類中的mongo_db@classmethod #使用classmethod標識deffrom_crawler(cls,crawler): #定義from_crawler方法8.2Scrapy應用#獲取settings.py文件中的數(shù)據(jù)庫的連接地址和數(shù)據(jù)庫名returncls(mongo_uri=crawler.settings.get('MONGO_URI'),mongo_db=crawler.settings.get('MONGO_DB'))defopen_spider(self,spider): #定義open_spider方法#連接MongoDB數(shù)據(jù)庫self.client=pymongo.MongoClient(self.mongo_uri)#創(chuàng)建數(shù)據(jù)庫self.db=self.client[self.mongo_db]defclose_spider(self,spider): #定義close_spider方法8.2Scrapy應用self.client.close() #斷開數(shù)據(jù)庫連接#定義process_item方法defprocess_item(self,item,spider):data={'index':item['index'],'title':item['title'],'link':item['link'],'newsNum':item['newsNum'],} #初始化datatable=self.db['news'] #新建集合table.insert_one(data) #向數(shù)據(jù)庫中插入數(shù)據(jù)returnitem #返回item8.2Scrapy應用定義了TextPipeline和MongoPipeline類后,還需要在settings.py文件的ITEM_PIPELINES中啟動這兩個Pipeline并設置調用順序,定義MongoDB數(shù)據(jù)庫的連接地址和數(shù)據(jù)庫名,修改后的代碼如下。ITEM_PIPELINES={#啟動TextPipeline,設置調用順序'BaiduSpider.pipelines.TextPipeline':300,#啟動MongoPipeline,設置調用順序'BaiduSpider.pipelines.MongoPipeline':400,}MONGO_URI='localhost' #設置數(shù)據(jù)庫的連接地址MONGO_DB='baidu' #設置數(shù)據(jù)庫名8.2Scrapy應用其中,ITEM_PIPELINES的鍵值是一個數(shù)字,表示調用優(yōu)先級,數(shù)字越小優(yōu)先級越高。在BaiduSpider目錄下,輸入“scrapycrawlnews”命令并運行,即可將爬取到的內容保存到MongoDB數(shù)據(jù)庫中。通過MongoDBCompass查看數(shù)據(jù)庫中的內容,如圖8-9所示。圖8-9MongoDBCompass查看數(shù)據(jù)庫中的內容8.2Scrapy應用8.2.7定制MiddlewareMiddleware分為DownloaderMiddleware和SpiderMiddleware,通過定制DownloaderMiddleware可以設置User-Agent、IP代理和下載頻率等;通過定制SpiderMiddleware能夠限制最大爬取深度,篩選未成功響應等。1.定制DownloaderMiddleware每個DownLoaderMiddleware都定義了一個類,而類中又定義了process_request()、process_response()和process_reception()等方法。DownLoaderMiddleware類在middlewares.py中的模板如圖8-10所示。8.2Scrapy應用圖8-10DownloaderMiddleware類模板8.2Scrapy應用定制一個DownLoaderMiddleware只需要實現(xiàn)其中一個或多個方法,其中最常用的是process_request()方法,它會被所有通過DownloaderMiddleware的Request調用,該方法具有如下兩個參數(shù)。(1)request:Request對象,表示需要處理的Request。(2)spider:Spider對象,表示此Request對應的Spider。該方法的返回值有4種(見表8-4),調用該方法時必須返回其中的一種。8.2Scrapy應用表8-4process_request()方法返回值的說明返回值類型說明NoneScrapy將繼續(xù)處理該Request,執(zhí)行其他DownloaderMiddleware的process_request()方法,直到Downloader執(zhí)行該Request得到Response后結束ResponseScrapy不會繼續(xù)調用其他DownloaderMiddleware的process_request()方法和process_exception()方法(或其他下載方法)。而DownloaderMiddleware的process_response()方法將會在每個Response返回時被調用RequestScrapy停止調用DownloaderMiddleware的process_request()方法,并重新調度返回的RequestIgnoreRequest拋出IgnoreRequest異常,該異常會交給所有DownloaderMiddleware的process_exception()方法進行處理;如果沒有任何一個方法處理該異常,那么Request的errorback()方法會被調用處理該異常;如果該異常還沒有被errorback()方法處理,那么它會被忽略且無記錄8.2Scrapy應用在BaiduSpider項目中,定制一個DownloaderMiddleware實現(xiàn)隨機設置請求頭中的User-Agent,即在middlewares.py中定義RandomUserAgentMiddleware類,添加的代碼如下。importrandom #設置random模塊#定義RandomUserAgentMiddleware類classRandomUserAgentMiddleware:def__init__(self): #定義__init__方法self.user_agent_list=['Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/70.0.3538.102Safari/537.36Edge/18.18363',8.2Scrapy應用'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/83.0.4103.97Safari/537.36','Mozilla/5.0(Windows;U;MSIE9.0;WindowsNT9.0;en-US)','Mozilla/5.0(compatible;MSIE9.0;WindowsNT6.1;Win64;x64;Trident/5.0;.NETCLR3.5.30729;.NETCLR3.0.30729;.NETCLR2.0.50727;MediaCenterPC6.0)','Mozilla/5.0(compatible;MSIE8.0;WindowsNT6.0;Trident/4.0;WOW64;Trident/4.0;SLCC2;.NETCLR2.0.50727;.NETCLR3.5.30729;.NETCLR3.0.30729;.NETCLR1.0.3705;.NETCLR1.1.4322)','Mozilla/5.0(Windows;U;WindowsNT5.1;zh-CN)AppleWebKit/523.15(KHTML,likeGecko,Safari/419.3)Arora/0.3(Change:287c9dfb30)',8.2Scrapy應用'Mozilla/5.0(X11;U;Linux;en-US)AppleWebKit/527+(KHTML,likeGecko,Safari/419.3)Arora/0.6','Mozilla/5.0(Windows;U;WindowsNT5.1;en-US;rv:pre)Gecko/20070215K-Ninja/2.1.1','Mozilla/5.0(Windows;U;WindowsNT5.1;zh-CN;rv:1.9)Gecko/20080705Firefox/3.0Kapiko/3.0','Mozilla/5.0(X11;Linuxi686;U;)Gecko/20070322Kazehakase/0.4.5','Mozilla/5.0(X11;U;Linuxi686;en-US;rv:)GeckoFedora/-1.fc10Kazehakase/0.5.6','Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/535.11(KHTML,likeGecko)Chrome/17.0.963.56Safari/535.11',8.2Scrapy應用'Mozilla/5.0(Macintosh;IntelMacOSX10_7_3)AppleWebKit/535.20(KHTML,likeGecko)Chrome/19.0.1036.7Safari/535.20'] #定義user_agent_list#定義process_request方法defprocess_request(self,request,spider):#在user_agent_list隨機選擇useragent=random.choice(self.user_agent_list)#設置請求頭中的User-Agentrequest.headers.setdefault('User-Agent',useragent)returnNone #返回None8.2Scrapy應用定制DownloaderMiddleware后,需要在settings.py文件的DOWNLOADER_MIDDLEWARES中啟動DownloaderMiddleware并設置調用順序,同時取消USER_AGENT設置(將其注釋掉即可),修改后的代碼如下。#USER_AGENT='Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/83.0.4103.97Safari/537.36' #注釋掉USER_AGENTDOWNLOADER_MIDDLEWARES={#啟動RandomUserAgentMiddleware,并設置調用順序'BaiduSpider.middlewares.RandomUserAgentMiddleware':350,}8.2Scrapy應用其中,DOWNLOADER_MIDDLEWARES的鍵值是一個數(shù)字,表示調用的優(yōu)先級,數(shù)字越小表示越靠近Scheduler,數(shù)字越大表示越靠近Downloader,換句話說,對于process_request()方法,數(shù)字越小優(yōu)先級越高,對于process_response()方法,數(shù)字越大優(yōu)先級越高。8.2Scrapy應用2.定制SpiderMiddleware每個SpiderMiddleware都定義了一個類,而類中又定義了process_input()、process_output()、process_reception()和process_start_requests()中的一個或多個方法。SpiderMiddleware類在middlewares.py中的模板如圖8-11所示。Scrapy默認提供并開啟的SpiderMiddleware已經(jīng)足夠滿足多數(shù)需求,故一般不需要手動修改。8.2Scrapy應用圖8-11SpiderMiddleware類模板8.2Scrapy應用.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲.Python網(wǎng)絡爬蟲SectionTitle實戰(zhàn)演練爬取中國大學MOOC網(wǎng)站課程信息實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息1.實戰(zhàn)目的練習使用Scrapy框架爬取中國大學MOOC網(wǎng)站數(shù)據(jù)。2.實戰(zhàn)內容使用Scrapy框架爬取中國大學MOOC網(wǎng)站搜索的課程信息(如Python),包括課程名稱、開課學校、課程類型、參與人數(shù)、課程概述、授課目標和預備知識,并將參與人數(shù)大于10000的課程存儲至MongoDB數(shù)據(jù)庫中。3.實戰(zhàn)分析(1)使用GoogleChrome瀏覽器打開中國大學MOOC網(wǎng)站(網(wǎng)址/),搜索“Python”,查看網(wǎng)頁源代碼,發(fā)現(xiàn)課程信息包含在“mocSearchBean.searchCourse.rpc?csrfKey=6d38afce3bd84a39b368f9175f995f2b”請求信息中(可在“Network”→“XHR”中查看),如圖8-12所示。實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息圖8-12課程信息實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息查看該請求的“Headers”信息,獲取請求的URL、請求方式和請求體,如圖8-13所示。在網(wǎng)頁中翻頁,通過分析發(fā)現(xiàn),每一網(wǎng)頁的請求體中的“pageIndex”信息不同(如第2頁為2),因此,可循環(huán)設置“pageIndex”信息,以獲取搜索到的所有課程信息。實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息圖8-13請求信息實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息(2)創(chuàng)建爬取中國大學MOOC網(wǎng)站的項目(如MOOCSpider)。(3)修改items.py。定義CourseItem類,在類中定義courseName(課程名稱)、university(開課學校)、category(課程類型)、enrollCount(參與人數(shù))、overview(課程概述)、objective(授課目標)和preliminaries(預備知識)。scrapystartprojectMOOCSpider #創(chuàng)建項目實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息classCourseItem(scrapy.Item):courseName=scrapy.Field() #定義課程名稱university=scrapy.Field() #定義開課學校category=scrapy.Field() #定義課程類型enrollCount=scrapy.Field() #定義參與人數(shù)overview=scrapy.Field() #定義課程概述objective=scrapy.Field() #定義授課目標preliminaries=scrapy.Field() #定義預備知識實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息(4)創(chuàng)建一個spider腳本(如course.py)。cdMOOCSpider #切換到MOOCSpider目錄scrapygenspidercourse #創(chuàng)建spider腳本實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息(5)修改course.py。由于啟動程序時發(fā)送的是POST請求,所以刪除默認的start_urls屬性,重寫start_requests()方法。其中使用scrapy.FormRequest()方法發(fā)送POST請求,表單提交數(shù)據(jù),指定回調方法為parse。在parse()方法中提取課程名稱、開課學校、課程類型和參與人數(shù),同時獲取學校縮寫和課程ID,拼接成新的URL(如/course/HENANNU-1003544138,其中HENANNU為學??s寫,1003544138為課程ID),并使用scrapy.Request()方法請求新的URL,指定回調方法為parse_section(),以提取課程概述、授課目標和預備知識。由于獲取的內容需要請求不同的網(wǎng)頁,所以在使用scrapy.Request()方法時需要使用meta參數(shù)傳遞item,并且使用深拷貝。實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息importscrapy #導入scrapy模塊#導入items模塊中的CourseItem類fromMOOCSpider.itemsimportCourseItemimportjson #導入json模塊fromcopyimportdeepcopy #導入deepcopy模塊#定義CourseSpider類classCourseSpider(scrapy.Spider):name='course' #初始化name#初始化allowed_domainsallowed_domains=['']實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息#重寫start_requests方法defstart_requests(self):#定義urlurl='/web/j/'\'mocSearchBean.searchCourse.rpc?csrfKey='\'6d38afce3bd84a39b368f9175f995f2b'foriinrange(7): #循環(huán)7次#定義data_strdata_dict={'keyword':'python','pageIndex':str(i+1),實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息'highlight':'true','orderBy':0,'stats':30,'pageSize':20}data_str=json.dumps(data_dict)data={'mocCourseQueryVo':data_str} #定義data#發(fā)送POST請求,指定回調方法為parseyieldscrapy.FormRequest(實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息method='POST',url=url,formdata=data,callback=self.parse,dont_filter=True)defparse(self,response): #定義parse方法data=response.body.decode('utf-8') #響應解碼#獲取課程列表course_list=json.loads(data)['result']['list']item=CourseItem() #初始化對象item實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息forcourseincourse_list: #遍歷#獲取mocCourseCardDto鍵值CourseCard=course['mocCourseCard']['mocCourseCardDto']#提取課程名稱,并寫入Itemitem['courseName']=CourseCard['name']#提取開課學校,并寫入Itemitem['university']=CourseCard['schoolPanel']['name']ifCourseCard['mocTagDtos']:#如果mocTagDtos鍵在字典中#提取課程類型,并寫入Itemitem['category']=CourseCard['mocTagDtos'][0]['name']else: #如果mocTagDtos鍵不在字典中 實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息item['category']='NULL'#課程類型賦值為NULL#提取參與人數(shù),并寫入Itemitem['enrollCount']=CourseCard['termPanel']['enrollCount']#提取學??s寫shortName=CourseCard['schoolPanel']['shortName']#提取課程IDcourse_id=course['courseId']#拼接URLurl='/course/'+\shortName+'-'+str(course_id) #指定回調方法為parse_section方法 實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息yieldscrapy.Request(url,meta={'item':deepcopy(item)},callback=self.parse_section)defparse_section(self,response): #定義parse_section方法item=response.meta['item'] #傳遞item#初始化item的“overview”為NULLitem['overview']='NULL'#初始化item的“objective”為NULLitem['objective']='NULL'#初始化item的“preliminaries”為NULLitem['preliminaries']='NULL'實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息#獲取節(jié)點列表course_section=response.xpath('//div[@id="content-section"]')[0]foriinrange(3,10,2): #循環(huán),間隔為2#定義節(jié)點路徑,提取節(jié)點文本path_str='div['+str(i)+']/span[2]/text()'text=course_section.xpath(path_str).extract()#定義節(jié)點路徑path='div['+str(i+1)+']/div//p//text()'if'課程概述'intext: #如果節(jié)點文本包含“課程概述”實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息#提取課程概述列表overview=course_section.xpath(path).extract()overview=''.join(overview) #連接列表中元素item['overview']=overview #寫入itemelif'授課目標'intext: #如果節(jié)點文本包含“授課目標”#提取授課目標列表objective=course_section.xpath(path).extract()objective=''.join(objective) #連接列表中元素item['objective']=objective #寫入itemelif'預備知識'intext: #如果節(jié)點文本包含“預備知識”實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息#提取預備知識列表preliminaries=course_section.xpath(path).extract()#連接列表中元素preliminaries=''.join(preliminaries)#寫入itemitem['preliminaries']=preliminariesyielditem #返回item實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息(6)修改pipelines.py。定義TextPipeline類,篩選出參與人數(shù)大于10000的課程,定義MongoPipeline類,將數(shù)據(jù)存儲至MongoDB數(shù)據(jù)庫。fromscrapy.exceptionsimportDropItem #導入DropItem模塊classTextPipeline(): #定義TextPipeline類defprocess_item(self,item,spider):#定義process_item方法#如果item中的“enrollCount”大于于10000ifitem['enrollCount']>10000:returnitem #返回itemelse:#如果item中的“enrollCount”小于等于10000實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息raiseDropItem('Missingitem')#刪除itemimportpymongo #導入pymongo模塊classMongoPipeline(): #定義MongoPipeline類def__init__(self,mongo_uri,mongo_db):#定義__init__方法self.mongo_uri=mongo_uri #初始化類中的mongo_uriself.mongo_db=mongo_db #初始化類中的mongo_db@classmethod #使用classmethod標識deffrom_crawler(cls,crawler): #定義from_crawler方法#獲取settings.py文件中數(shù)據(jù)庫的連接地址和數(shù)據(jù)庫名returncls(實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息mongo_uri=crawler.settings.get('MONGO_URI'),mongo_db=crawler.settings.get('MONGO_DB'))defopen_spider(self,spider): #定義open_spider方法#連接MongoDB數(shù)據(jù)庫self.client=pymongo.MongoClient(self.mongo_uri)#創(chuàng)建數(shù)據(jù)庫self.db=self.client[self.mongo_db]defclose_spider(self,spider): #定義close_spider方法self.client.close() #斷開數(shù)據(jù)庫連接defprocess_item(self,item,spider):#定義process_item方法data={實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息'課程名稱':item['courseName'],'開課學校':item['university'],'課程類型':item['category'],'參與人數(shù)':item['enrollCount'],'課程概述':item['overview'],'授課目標':item['objective'],'預備知識':item['preliminaries'],} #初始化datatable=self.db['course'] #新建集合table.insert_one(data) #向數(shù)據(jù)庫中插入數(shù)據(jù)returnitem #返回item實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息(7)修改middlewares.py。定義RandomUserAgentMiddleware類實現(xiàn)隨機設置請求頭的User-Agent。importrandom #導入random#定義RandomUserAgentMiddleware類classRandomUserAgentMiddleware:def__init__(self): #定義__init__方法self.user_agent_list=['Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/70.0.3538.102Safari/537.36Edge/18.18363',實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/83.0.4103.97Safari/537.36','Mozilla/5.0(Windows;U;MSIE9.0;WindowsNT9.0;en-US)','Mozilla/5.0(compatible;MSIE9.0;WindowsNT6.1;Win64;x64;Trident/5.0;.NETCLR3.5.30729;.NETCLR3.0.30729;.NETCLR2.0.50727;MediaCenterPC6.0)','Mozilla/5.0(compatible;MSIE8.0;WindowsNT6.0;Trident/4.0;WOW64;Trident/4.0;SLCC2;.NETCLR2.0.50727;.NETCLR3.5.30729;.NETCLR3.0.30729;.NETCLR1.0.3705;.NETCLR1.1.4322)','Mozilla/5.0(Windows;U;WindowsNT5.1;zh-CN)AppleWebKit/523.15(KHTML,likeGecko,Safari/419.3)Arora/0.3(Change:287c9dfb30)',實戰(zhàn)演練——爬取中國大學MOOC網(wǎng)站課程信息'Mozilla/5.0(X11;U;Linux;en-US)AppleWebKit/527+(KHTML,likeGecko,Safari/419
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 5G+智慧教育項目背景與目標
- 和聲課的心得體會(5篇)
- 唯美晚安感言150句
- 高爐煉鐵工練習復習測試有答案
- 持證上崗信貸初級復習測試有答案
- 蝦類專業(yè)基礎知識題庫單選題100道及答案解析
- 國有企業(yè)專項合規(guī)計劃的制定與執(zhí)行精講課件
- 《學前兒童衛(wèi)生保健》 教案 8 模塊三學前兒童的營養(yǎng)衛(wèi)生
- 第1章 醫(yī)藥國際貿易導論課件
- 2024屆上海市虹口區(qū)復興高中高三下學期3月模擬考試數(shù)學試題
- 音樂風格分類數(shù)學建模
- 小班生活區(qū)域活動環(huán)境創(chuàng)設 - 上海學前教育網(wǎng)
- 小王子英文-(2)ppt課件
- 王家?guī)X煤礦主斜井井口房施工方案
- 二年級上冊數(shù)學練習題集及作業(yè)設計意圖
- 二年級上冊數(shù)學試題-表內除法 單元測試 蘇教版
- 三方共管賬戶資金監(jiān)管協(xié)議書
- 物權法知識點
- 定期清洗消毒空調及通風設施的制度
- 護理質量改善項目申報書
- 熱軋H型鋼理論重量表
評論
0/150
提交評論