安裝Scrapy
在安裝Scrapy之前,需要先安裝Twisted。Twisted可以使用pip安裝,如果直接安裝Scrapy,在安裝過程中就會出現報錯信息。
Windows下安裝Scrapy:有很多種方法,本人直接使用pip安裝。(這篇博客不想在安裝上多費篇幅,網上都能查的到。)
cmd命令行:
pip install scrapy
創建Scrapy項目
在cmd上將路徑切換到工作目錄(也就是你想將工程放在的目錄):
scrapy startproject 項目名稱
項目創建完畢。
Scrapy項目文件說明
創建項目後,在項目文件夾中看到目錄結構如下(本人是使用IDE查看目錄結構的,我的項目名稱是nbaspider):
其中spiders文件夾下的itcast.py和nba.txt文件一開始是沒有的,後面再娓娓道來。
- 第一層文件夾就是項目名nbaspider,沒啥好說的。
- 第二層中是一個與項目名同名的文件夾nbaspider(模塊/包,所有項目代碼都在這個模塊裏添加)和一個文件scrapy.cfg(顧名思義是整個Scrapy項目的配置文件)。
我們可以看看這個scrapy.cfg文件裏面有什麼:
整個文件只聲明瞭兩件事:一是定義默認設置文件的位置爲nbaspider模塊下的settings文件,二是定義項目名稱爲nbaspider。
- 第三層中有如下文件:
spiders文件夾其實也是一個模塊。
第三層的文件看起來很多,其實有用的也就三個文件:
items.py:定義存儲數據對象,主要銜接spiders(文件夾)和pipelines.py。
pipelines.py:數據存儲,數據格式以字典形式表現,字典的鍵是items.py定義的變量。
settings.py:是上層目錄中scrapy.cfg定義的設置文件,主要配置爬蟲信息,如請求頭、中間件和延時設置等。
_pycache_文件夾中的.pyc文件都是同名Python程序編譯得到的字節碼文件,settings.pyc是settings.py的字節碼文件,據說可以加快程序的運行速度,從“cache”(高速緩存)一詞就可窺探其作用。
middlewares.py文件是介於Scrapy的request/response處理的鉤子框架,用於全局修改Scrapy request和response的一個輕量、底層的系統。
至於_init_.py文件,它是個空文件,在此處的唯一作用就是將它的上級目錄變成了一個模塊,也就是說第二層的nbaspider文件夾沒有_init_.py文件,就只是一個單純的文件夾,在任何一個目錄下添加一個空的_init_.py文件,就會將該文件夾編程模塊化,可以供Python導入使用。
Scrapy爬蟲編寫
在編寫爬蟲之前我們還需創建一個基礎爬蟲文件,也就是上文提到的itcast.py(當然文件名是自定義的),進入nbaspider模塊,在cmd中輸入:
scrapy genspider itcast mtime.com
就會在spiders文件夾下創建該文件,spiders文件夾用於編寫爬蟲規則,可以在已有的_init_.py文件中編寫具體的爬蟲規則,但實際開發中可能含有多個爬蟲規則,所以建議一個爬蟲規則用一個文件表示,這樣便於維護和管理。
這樣就可以開始在Scrapy框架下的幾個文件裏開始“填空”編寫爬蟲了:
- settings.py:其中有大量註釋內容(配置代碼、配置說明、相應的官方文檔鏈接),根據需要去掉註釋。
- items.py:Scrapy已生成相關的代碼及文檔說明,開發者只需在此基礎上定義類屬性即可。
就我的項目來說,我需要爬取三項,所以定義三個類屬性,scrapy.Field()是Scrapy的特有對象,其主要作用是處理併兼容不同的數據格式,開發者在定義類屬性時無需考慮爬取數據的格式,Scrapy會對數據格式做相應處理。
- itcast.py:用於編寫爬蟲規則。
在該文件中,首先導入了scrapy模塊,然後從模塊nbaspider中的items文件中導入了NbaspiderItem類,也就是上述定義需要爬取內容的類。
name定義的是爬蟲名。allowed_domains定義的是域範圍,也就是爬蟲只能在這個域內爬取。start_urls定義的是爬取的網頁,最好使用列表類型,以便隨時在後面添加要爬取的網頁。
parse函數的參數response就是請求網頁後返回的數據。然後利用選擇器提取所需內容,選擇器在下面講解。items定義一個空列表用於返回多個item的列表。subSelector在上面用xpath選取了符合要求的內容組成列表,然後用for循環遍歷這個列表,循環裏,定義一個item初始化爲一個NbaspiderItem類,然後下面就是用xpath選取內容給這個類的各個屬性賦值。
其中有個比較迷惑新手的問題,即scrapy中xpath使用extract()的時候[0]位置問題,參考:
https://www.aimks.com/when-xpath-uses-extract-in-scrapy-position-analysis.html
- pipelines.py:Scrapy已自動生成類NbaspiderPipeline,類NbaspiderPipeline就是setting.py配置ITEM_PIPLINES的內容。數據存儲主要在類方法process_item()中執行。
運行爬蟲
回到scrapy.cfg文件的統計目錄下(實際上只要是在nbaspider項目下的任意目錄中執行都行),執行cmd:
scrapy crawl itcast
Scrapy選擇器XPath和CSS
Scrapy提取數據有自己的一套機制,他們被稱作選擇器(selectors),通過特定的XPath或者CSS表達式來選擇HTML文件中的某個部分。XPath是一門用來在XML文件中選擇節點的語言,也可以用在HTML上。CSS是一門將HTML文檔樣式化的語言,選擇器由它定義,並與特定的HTML元素的樣式相關聯。
XPath和CSS選擇器都可以嵌套使用,可以互相嵌套。
XPath選擇器:
表達式 | 描述 |
---|---|
nodename | 選取此節點的所有子節點。 |
/ | 從根節點選取。 |
// | 從匹配選擇的當前節點選擇文檔中的節點,而不考慮它們的位置。 |
. | 選取當前節點。 |
.. | 選取當前節點的父節點。 |
@ | 選取屬性。 |
通配符 | 描述 |
---|---|
* | 匹配任何元素節點。 |
@* | 匹配任何屬性節點。 |
node() | 匹配任何類型的節點。 |
路徑表達式 | 結果 |
---|---|
/bookstore/book[1] | 選取屬於 bookstore 子元素的第一個 book 元素。 |
/bookstore/book[last()] | 選取屬於 bookstore 子元素的最後一個 book 元素。 |
/bookstore/book[last()-1] | 選取屬於 bookstore 子元素的倒數第二個 book 元素。 |
/bookstore/book[position()<3] | 選取最前面的兩個屬於 bookstore 元素的子元素的 book 元素。 |
//title[@lang] | 選取所有擁有名爲 lang 的屬性的 title 元素。 |
//title[@lang='eng'] | 選取所有 title 元素,且這些元素擁有值爲 eng 的 lang 屬性。 |
/bookstore/book[price>35.00] | 選取 bookstore 元素的所有 book 元素,且其中的 price 元素的值須大於 35.00。 |
/bookstore/book[price>35.00]/title | 選取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值須大於 35.00。 |
路徑表達式 | 結果 |
---|---|
//book/title | //book/price | 選取 book 元素的所有 title 和 price 元素。 |
//title | //price | 選取文檔中的所有 title 和 price 元素。 |
/bookstore/book/title | //price | 選取屬於 bookstore 元素的 book 元素的所有 title 元素,以及文檔中所有的 price 元素。 |
CSS選擇器:
選擇器 | 值 | 說明 |
---|---|---|
.class | .intro | 選擇class="intro"的所有元素 |
#id | #firstname | 選擇id="firstname"的所有元素 |
* | * | 選擇所有元素 |
element | p | 選擇所有<p>元素 |
element,element | div,p | 選擇所有<div>元素和所有<p>元素 |
element element | div p | 選擇<div>元素內部的所有p元素 |
[attribute] | [target] | 選擇帶有target屬性的所有元素 |
[attribute=value] | [target=_blank] | 選擇target="_blank"的所有元素 |