標籤:XML python2.x 分享圖片 關係 頁面 intro info int 輸出
本章將從案例開始介紹python scrapy架構,更多內容請參考:python學習指南
入門案例學習目標
- 建立一個Scrapy項目
- 定義提取的結構化資料(Item)
- 編寫爬取網站的Spider並提取出結構化資料(Item)
- 編寫Item Pipelines來儲存提取到的Item(即結構化資料)
一、建立項目(scrapy startproject)
- 在開始爬取之前,必須建立一個新的Scrapy項目。進入自訂的項目目錄中,運行下列命令:
scrapy startproject cnblogSpider
- 其中,cnblogSpider為項目名稱,可以看到將會建立一個cnblogSpider檔案夾,目錄結構大致如下:
scrapy.cfg:項目部署檔案
cnblogSpider/: 該項目的python模組,之後可以在此加入代碼
cnblogSpider/items.py: 項目中的item檔案。
cnblogSpider/pipelines.py: 項目中的Pipelines檔案。
cnblogSpider/settings.py: 項目的設定檔。
cnblogSpider/spiders/: 放置Spider代碼的目錄。
二、明確目標(mySpider/items.py)
我們打算抓取:"http://www.cnblogs.com/miqi1992/default.html?page=2" 網站裡部落格地址、標題、建立時間、文本。
開啟cnblogSpider目錄下的items.py
item定義結構化資料欄位,用來儲存爬取到的資料,有點像Python中的dict,但是提供了一些額外的保護減少錯誤。
可以通過建立一個scrapy.item類,並且定義類型為scrapy.Field的類屬性來定義一個Item(可以理解成類似於ORM的映射關係)。
接下來,建立一個CnblogspiderItem類,和模型item模型(model)。
```python
import scrapy
class CnblogspiderItem(scrapy.Item):
# define the fields for your item here like:
url = scrapy.Field()
time = scrapy.Field()
title = scrapy.Field()
content = scrapy.Field()
```
三、製作爬蟲(spiders/cnblogsSpider.py)
爬蟲功能主要分兩步:
1. 爬資料
在目前的目錄下輸入命令,將在cnblogSpider/spiders目錄下建立一個名為cnblog的爬蟲,並制定爬取域的範圍:
scrapy genspider cnblog "cnblogs.com"
開啟cnblogSpider/spiders目錄下的cnblog,預設增加了下列代碼:
```python
-- coding: utf-8 --import scrapy
class CnblogSpider(scrapy.Spider):
name = ‘cnblog‘
allowed_domains = [‘cnblogs.com‘]
start_urls = [‘http://cnblogs.com/‘]
def parse(self, response): pass
```
其實也可以由我們自行建立cnblog.py並編寫上面的代碼,只不過使用命令可以免去編寫固定代碼的麻煩
要建立一個Spider,你必須用scrapy.Spider類建立一個子類,並確定了三個強制的屬性和一個方法。
name = "": 這個爬蟲的識別名稱,必須是唯一的,在不同的爬蟲必須定義不同的名字。
allow_domains=[]: 是搜尋的網域名稱範圍,也就是爬蟲的約束地區,規定爬蟲只爬取這個網域名稱下的網頁,不存在的URL會被忽略。
start_urls=():爬取的URL元祖/列表。爬蟲從這裡開始爬取資料,所以,第一次下載的資料將會從這些urls開始。其他子URL將會從這些起始URL中繼承性產生。
parse(self, response):解析的方法,每個初始URL完成下載後將被調用,調用的時候傳入從每一個URL傳回的Response對象來作為唯一參數,主要作用如下:
- 負責解析返回的網頁資料(respose.body),提取結構化資料(產生item)
- 產生需要下一頁的URL請求
將start_urls的值改為需要爬取的第一個url:
start_urls=("http://www.cnblogs.com/miqi1992/default.html?page=2")
修改parse()方法
def parse(self, response): filename = "cnblog.html" with open(filename, 'w') as f: f.write(response.body)
然後運行一下看看,在cnblogSpider目錄下運行:
scrapy crawl cnblog
是的,就是cnblog,看上面代碼,它是CnblogSpider類的name屬性,也就是scrapy genspider命令的唯一爬蟲名。
運行之後,如果列印的日誌出現[scrapy]INFO: Spider closed(finished),代表執行完成。之後當前檔案夾中就出現了一個cnblog.html檔案,裡面就是我們剛剛要爬取的網頁的全部原始碼資訊。
#注意,Python2.x預設編碼環境是ASCII,當和取回的資料編碼格式不一致時,可能會造成亂碼;#我們可以指定儲存內容的編碼格式,一般情況下,我們可以在代碼最上方添加:import osreload(sys)sys.setdefaultencoding('utf-8')#這三行代碼是Python2.x裡面解決中文編碼的萬能鑰匙,警告這麼多年的吐槽後Python3學乖了,預設編碼是Unicode了
2.爬資料
- 爬取整個網頁完畢,接下來就是取過程了,首先觀察頁面源碼:
<div class="day"> <div class="dayTitle">...</div> <div class="postTitle">...</div> <div class="postCon">...</div></div>
- XPath運算式如下:
- 所有文章:.//*[@class=‘day‘]
- 文章發表時間:.//*[@class=‘dayTitle‘]/a/text()
- 文章標題內容:.//*[@class=‘postTitle‘]/a/text()
- 文章摘要內容:.//*[@class=‘postCon‘]/div/text()
- 文章連結:.//*[@class=‘postTitle‘]/a/@href
是不是一目瞭然?直接上XPath開始提取資料吧。
我們之前在cnblogSpider/items.py裡定義了一個CnblogItem類。這裡引入進來
from cnblogSpider.items import CnblogspiderItem
然後將我們得到的資料封裝到一個CnblogspiderItem對象中,可以儲存每個部落格的屬性:
```python
form cnblogSpider.items import CnblogspiderItem
def parse(self, response):
# print(response.body)
# filename = "cnblog.html"
# with open(filename, ‘w‘) as f:
# f.write(response.body)
#存放部落格的集合 items = [] for each in response.xpath(".//*[@class='day']"): item = CnblogspiderItem() url = each.xpath('.//*[@class="postTitle"]/a/@href').extract()[0] title = each.xpath('.//*[@class="postTitle"]/a/text()').extract()[0] time = each.xpath('.//*[@class="dayTitle"]/a/text()').extract()[0] content = each.xpath('.//*[@class="postCon"]/div/text()').extract()[0] item['url'] = url item['title'] = title item['time'] = time item['content'] = content items.append(item) #直接返回最後資料 return items
```
儲存資料
scrapy儲存資訊的最簡單的方法主要有四種, -o 輸出指定格式的檔案,命令如下:
#json格式,預設為Unicode編碼scrapy crawl cnblog -o cnblog.json#json lines格式,預設為Unicode編碼scrapy crawl cnblog -o cnblog.jsonl#csv逗號運算式,可用excel開啟scrapy crawl cnblog -o cnblog.csv#xml格式scrapy crawl cnblog -o cnblog.xml
思考如果將代碼改成下面形式,結果完全一樣請思考yield在這裡的作用:
form cnblogSpider.items import CnblogspiderItemdef parse(self, response): # print(response.body) # filename = "cnblog.html" # with open(filename, 'w') as f: # f.write(response.body) #存放部落格的集合 # items = [] for each in response.xpath(".//*[@class='day']"): item = CnblogspiderItem() url = each.xpath('.//*[@class="postTitle"]/a/@href').extract()[0] title = each.xpath('.//*[@class="postTitle"]/a/text()').extract()[0] time = each.xpath('.//*[@class="dayTitle"]/a/text()').extract()[0] content = each.xpath('.//*[@class="postCon"]/div/text()').extract()[0] item['url'] = url item['title'] = title item['time'] = time item['content'] = content # items.append(item) #將擷取到的資料交給pipelines yield item #直接返回最後資料,不經過pipelines #return items
參考:
- Python參考手冊
Python爬蟲Scrapy(二)_入門案例