scrapy框架入門
scrapy框架
Scrapy是用純Python實現一個為了爬取網站數據、提取結構性數據而編寫的應用框架,用途非常廣泛。
框架的力量,用戶只需要定制開發幾個模塊就可以輕松的實現一個爬蟲,用來抓取網頁內容以及各種圖片,非常之方便。
Scrapy 使用了 Twisted’tw?st?d異步網絡框架來處理網絡通訊,可以加快我們的下載速度,不用自己去實現異步框架,并且包含了各種中間件接口,可以靈活的完成各種需求。
簡單來說就是一個爬蟲的應用框架,更方便爬取。爬取效率高,可配置和可拓展程度非常高,幾乎可以應用所有的反爬網站。
架構圖解
每當我們談到scrapy框架的時候,都會用這個圖來進行講解:
它可以分為如下的幾個部分。Engine。引擎,處理整個系統的數據流處理、觸發事務,是整個框架的核心。
Item。項目,它定義了爬取結果的數據結構,爬取的數據會被賦值成該Item對象。Scheduler。調度器,接受引擎發過來的請求并將其加入隊列中,在引擎再次請求的時候將請求提供給引擎。
Downloader。下載器,下載網頁內容,并將網頁內容返回給蜘蛛。Spiders。蜘蛛,其內定義了爬取的邏輯和網頁的解析規則,它主要負責解析響應并生成提取結果和新的請求。
Item Pipeline。項目管道,負責處理由蜘蛛從網頁中抽取的項目,它的主要任務是清洗、驗證和存儲數據。
Downloader Middlewares。下載器中間件,位于引擎和下載器之間的鉤子框架,主要處理引擎與下載器之間的請求及響應。
Spider Middlewares。蜘蛛中間件,位于引擎和蜘蛛之間的鉤子框架,主要處理蜘蛛輸入的響應和輸出的結果及新的請求。
這些組件相互協作,不同不同組件完成工作的不同、組件對異步處理的支持,Scrapy最大限度地利用了網絡帶寬,大大提高了數據爬取和處理的效率。
Scrapy項目結構
scrapy是通過命令行來創建的,創建之后文件結構如下圖所示:
下面這個以我自己創建的第一個scrapy項目來進行分級圖解的:大致也是這種結構
其中, mySpider 為項目名稱,可以看到將會創建一個 mySpider 文件夾,目錄結構大致如下:
下面來簡單介紹一下各個主要文件的作用:
scrapy.cfg :項目的配置文件,定義了項目的配置文件路徑。部署相關信息的內容
items.py :項目的目標文件,所有的Item Pipeline的定義都可以放在這里面。
pipelines.py :項目的管道文件,定義了Item Pipeline的實現都可以放在這里。
settings.py :項目的設置文件,定義了項目的全局配置
spiders/ :存儲爬蟲代碼目錄,其中包含了一個個Spider的實現,每個Spider都有一個文件。
上面這些都是理論基礎,下面我們就開始動手實踐,慢慢去理解怎么用Scrapy爬取,以及怎么搭建Scrapy框架。
Scrapy 入門
我將簡單介紹一下項目的構建,完成一遍Scrapy抓取流程,通過這個流程,我們可以對Scrapy的基本用法和原理有大體的了解。這次我們要采集的是光明網的新標題,時間,網址信息。
準備工作
首先我們需要安裝Scrapy框架
安裝還是類似其他第三方庫的方法是一樣的
pip install scrapy
創建項目
創建一個scrapy項目,項目文件可以直接用scrapy命令生成,命令如下所示:
scrapy startproject news
這個命令可以在任何文件夾運行,如果提示權限問題,可以加一個sudo運行該命令。這個命令會創建一個news的文件夾,文件夾結構就是我上面那個圖。
創建Spider
Spider是我們自己定義的一個類,Scrapy用它來從網頁抓取內容,并解析抓取的結果,不過這個類繼承Scrapy提供的Spider類scrapy,還要定義Spider的名稱和起始請求,以及怎樣處理爬取后的結果。
我們也可以通過命令來創建一個Spider,比如要生成news_1這個Spider,可以執行如下命令:
cd C:\Users\lixue\Desktop\news\news
scrapy genspider news_1 news.gmw.cn
我們在進入剛才創建的news文件夾下面,然后執行genspider命令。第一個參數是Spider的名稱,第二個參數是網站域名。執行完畢后,spider文件夾就多了一個news_1.py,我們可以看看剛剛創建的Spider:
import scrapy
class News1Spider(scrapy.Spider):
name = 'news_1'
allowed_domains = ['news.gmw.cn']
start_urls = ['http://news.gmw.cn']
def parse(self, response):
pass
這里面有三個屬性-name、allowed_domains、還有一個方法parse.
name :這個爬蟲的識別名稱,必須是唯一的,在不同的爬蟲必須定義不同的名字。
allow_domains 是搜索的域名范圍,也就是爬蟲的約束區域,規定爬蟲只爬取這個域名下的網頁,不存在的URL會被忽略。
start_urls 爬取的URL元祖/列表。爬蟲從這里開始抓取數據,所以,第一次下載的數據將會從這些urls開始。其他子URL將會從這些起始URL中繼承性生成。
parse(self, response) :解析的方法,每個初始URL完成下載后將被調用,調用的時候傳入從每一個URL傳回的Response對象來作為唯一參數,主要作用如下:
負責解析返回的網頁數據(response.body),提取結構化數據(生成item)
生成需要下一頁的URL請求。將start_urls的值修改為需要爬取的第一個url.
我們采集的是光明網上的幾大新聞版塊的新聞,所以我設置的start_urls包含多個url的列表。(前提是這些新聞版塊的網頁結構相同)
start_urls = ['http://news.gmw.cn/node_23548.htm','http://news.gmw.cn/node_23707.htm','http://news.gmw.cn/node_23547.htm','http://news.gmw.cn/node_23545.htm','http://news.gmw.cn/node_23708.htm','http://news.gmw.cn/node_23709.htm']
創建Item
Item是保存爬取數據的容器,它的使用方法和字典類似,不過相比字典,Item多了保護機制,防止拼寫錯誤或者自定義字段錯誤。
創建Item需要繼承scrapy.Item類,并且定義類型為scrapy.Field字段,我們采集信息有title,url ,time
定義Item,此時將items.py修改如下:
import scrapy
class NewsItem(scrapy.Item):
title =scrapy.Field()
url =scrapy.Field()
time =scrapy.Field()
這里定義了三個字段,我們爬取會使用這個Item.
解析Response
上文中我們看到,parse()方法的參數resposne的英文start_urls里面的鏈接爬取后的查詢查詢結果。在所以parse方法中,可以我們直接對response變量所有游戲的內容進行解析,比如瀏覽請求結果的網頁源代碼,或者進一步分析源代碼內容,或者找出結果中的鏈接而得到下一個請求。我們可以看到網頁中既有我們想要的結果,又有下一頁的鏈接,這兩部分內容我們都要進行處理。首先看看網頁結構,如下圖所示。
我們觀察網頁結構發現新聞版塊是多條結合的,它們的結構相似,每條新聞區塊包含上面的三個字段,我們接下來用xpath解析器來進行選擇,parse方法的改寫如下所示:
def parse(self, response):
selecter = Selector(text = response.body.decode('utf-8'))
url =selecter.xpath('//div[(@class = "channelLeftPart")]/div/ul/li/span[1]/a[1]/@href').extract()
title =selecter.xpath('//div[(@class = "channelLeftPart")]/div/ul/li/span[1]/a/text()').extract()
news_time =selecter.xpath('//div[(@class = "channelLeftPart")]/div/ul/li/span[2]/text()').extract()
scrapy中包含了一個Selector這個獨立的模塊。我們可以直接用Selector這個類來構建一個選擇器對象,然后調用它的相關方法如xpath(),css()來提取數據,這些和之前的xpath,css一樣的用法。
由于scrapy是一個框架型的,我們在提取數據的時候少不了測試,但我們單獨測試又太麻煩,所以scrapy提供一個shell命令,來進行測試。
Scrapy shell
Scrapy終端是一個交互終端,供您在未啟動spider的情況下嘗試及調試您的爬取代碼。 其本意是用來測試提取數據的代碼,不過您可以將其作為正常的Python終端,在上面測試任何的Python代碼。
該終端是用來測試XPath或CSS表達式,查看他們的工作方式及從爬取的網頁中提取的數據。 在編寫您的spider時,該終端提供了交互性測試您的表達式代碼的功能,免去了每次修改后運行spider的麻煩。
啟動方式:
scrapy shell <url>
這里我們測試采用一個新聞網址就可以:
scrapy shell http://news.gmw.cn/node_23548.htm
這樣運行之后,便能看到那個shell 命令窗口。
然后我們需要運行調用的第三庫
然后再來測試我們的解析提取部分:
最后我們可以看看提取的東西:
最后我們發現我們都是正確提取到的標簽的。
使用Item
上面定義了Item,接下來就要使用它了。Item可以理解為一個字典,不過在聲明的時候需要實例化,然后依次用剛才解析的結果賦值給Item的每一個字段,最后將Item返回即可。
我們改寫那個Spider如下:
import scrapy
from scrapy import Request,Selector
from news.items import NewsItem
class News1Spider(scrapy.Spider):
name = 'news_1'
# allowed_domains = ['http://news.gmw.cn']
start_urls = ['http://news.gmw.cn/node_23548.htm','http://news.gmw.cn/node_23707.htm','http://news.gmw.cn/node_23547.htm','http://news.gmw.cn/node_23545.htm','http://news.gmw.cn/node_23708.htm','http://news.gmw.cn/node_23709.htm']
def parse(self, response):
selecter = Selector(text = response.body.decode('utf-8'))
url =selecter.xpath('//div[(@class = "channelLeftPart")]/div/ul/li/span[1]/a[1]/@href').extract()
title =selecter.xpath('//div[(@class = "channelLeftPart")]/div/ul/li/span[1]/a/text()').extract()
news_time =selecter.xpath('//div[(@class = "channelLeftPart")]/div/ul/li/span[2]/text()').extract()
for i in range(len(url)):
item =NewsItem()
item['url'] =url[i]
item['title'] =title[i]
item['time'] = news_time[i]
yield item
后續Request
上面這些操作從初始頁面抓取內容,但是下一頁改怎么抓取,這樣我們需要從當前頁面找到信息生成下一頁的請求的鏈接,從而來構造下一個請求,這樣循環迭代,從而實現整站的爬取。
將剛才的新聞頁面拉到最低部,我們可以看到下一頁的鏈接:
發現鏈接是node_23548_2.htm
,全鏈接是http://news.gmw.cn/node_23548_2.htm
構造請求時需要用到scrapy.Request,這里我們需要傳入兩個參數----url和callback.
url:它是請求鏈接。
callback:它是回調函數當指定了該回調函數的請求完成之后,獲取到響應,引擎會將該響應作為參數傳遞給這個回調函數回調函數進行解析或生成下一個請求,函數回調文如上的parse()所示。
下面我們來編寫一下翻頁請求的代碼:
next =selecter.xpath('//div[(@class = "channelLeftPart")]/div/div/center/a[last()-1]/@href').extract()
if next:
print(111111111111)
url_nextpage ='http://news.gmw.cn/'+next[0]
yield scrapy.Request(url= url_nextpage,callback=self.parse)
這個判斷條件是起到停止翻頁的作用,一旦沒有找到下一頁的鏈接,就停止下面,下面我們可以看看完整的代碼:
import scrapy
from scrapy import Request,Selector
from news.items import NewsItem
class News1Spider(scrapy.Spider):
name = 'news_1'
# allowed_domains = ['http://news.gmw.cn']
start_urls = ['http://news.gmw.cn/node_23548.htm','http://news.gmw.cn/node_23707.htm','http://news.gmw.cn/node_23547.htm','http://news.gmw.cn/node_23545.htm','http://news.gmw.cn/node_23708.htm','http://news.gmw.cn/node_23709.htm']
def parse(self, response):
selecter = Selector(text = response.body.decode('utf-8'))
url =selecter.xpath('//div[(@class = "channelLeftPart")]/div/ul/li/span[1]/a[1]/@href').extract()
title =selecter.xpath('//div[(@class = "channelLeftPart")]/div/ul/li/span[1]/a/text()').extract()
news_time =selecter.xpath('//div[(@class = "channelLeftPart")]/div/ul/li/span[2]/text()').extract()
for i in range(len(url)):
item =NewsItem()
item['url'] =url[i]
item['title'] =title[i]
item['time'] = news_time[i]
yield item
next =selecter.xpath('//div[(@class = "channelLeftPart")]/div/div/center/a[last()-1]/@href').extract()
if next:
print(111111111111)
url_nextpage ='http://news.gmw.cn/'+next[0]
yield scrapy.Request(url= url_nextpage,callback=self.parse)
當我們進行完上述代碼修改,我們的scrapy也就寫好了,接下來就是運行。
運行
這里我們首先要進入scrapy項目的文件夾
接下來進入目錄,運行如下命令:
cd C:\Users\lixue\Desktop\news\news
scrapy crawl news_1
運行完這個,我們就可以看到Scrapy的運行結果了。
保存文件
當我們就按上面運行完scrapy后,我們只在控制臺看到輸出結果。如果想保存結果該怎么辦呢?
其實要完成這個命令我們不需要額外的命令,我們只需要看需要保存文件的要求,然后選擇對應的方法進行保存,比如我們想要將其保存為JSON 格式的文件,我們應該這樣做:
scrapy crawl news_1 -o news_1.json
運行完這個,在我們剛才cd的路徑下面就有一個news_1.json 文件了json格式,默認為Unicode編碼。我們打開那個文件編碼需要進行轉換。
如果我們想要一個Item 輸出一一行JSON,后綴名為jl,為jsonline的縮寫,命令如下:
scrapy crawl news_1 -o news_1.jsonlines
或者:
scrapy crawl news_1 -o teachers.jl
scrapy還支持保存輸出保存為csv,xml文件,命令分別是:
保存為csv文件:
scrapy crawl news_1 -o news_1.csv
保存為xml文件:
scrapy crawl news_1 -o news_1.xml
我們可以分別看看運行的結果:
最后我們采集的數據大概有4800條,我們大概不用一分鐘就采集到4800條新聞,是不是很快,大家可以一起來使用一下,我這次也大致介紹這些,其實這個爬蟲還存在一些問題,你們可以去查看一下數據,下篇博客我會深入講解scrapy,然后完善這個爬蟲。有不懂的地方可以查閱官方文檔。
智能推薦
Python爬蟲day7—Scrapy框架入門
Scrapy爬蟲框架入門 概述 Scrapy是Python開發的一個非常流行的網絡爬蟲框架,可以用來抓取Web站點并從頁面中提取結構化的數據,被廣泛的用于數據挖掘、數據監測和自動化測試等領域。下圖展示了Scrapy的基本架構,其中包含了主要組件和系統的數據處理流程(圖中帶數字的紅色箭頭)。 組件 Scrapy引擎(Engine):Scrapy引擎是用來控制整個系統的數據處理流程。 調度器(Sche...
Python爬蟲學習教程:Scrapy爬蟲框架入門
Python爬蟲學習教程:Scrapy概述 Scrapy是Python開發的一個非常流行的網絡爬蟲框架,可以用來抓取Web站點并從頁面中提取結構化的數據,被廣泛的用于數據挖掘、數據監測和自動化測試等領域。下圖展示了Scrapy的基本架構,其中包含了主要組件和系統的數據處理流程(圖中帶數字的紅色箭頭)。 組件 Scrapy引擎(Engine):Scrapy引擎是用來控制整個系統的數據處理流程。 調度...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
猜你喜歡
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...
Linux C系統編程-線程互斥鎖(四)
互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...
統計學習方法 - 樸素貝葉斯
引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...
styled-components —— React 中的 CSS 最佳實踐
https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...