1. 程式人生 > >python之scrapy(三)spider的用法

python之scrapy(三)spider的用法

Scrapy框架中Spider的用法

 

在Scrapy裡面,要抓取網站的連結配置、抓取邏輯、解析邏輯裡,都是在Spider裡面去完成的。

一、Spider的執行流程

在實現Scrapy爬蟲專案裡面,最核心的就是Spider類了,它定義瞭如何爬取某個網站的流程和解析方式。簡單來講,Spider就做兩件事情:

  • 定義爬取的動作

  • 分析爬取下來的網頁

對於Spider類來說,整個流程如下,可以參考中文官方文件

  • 以初始的URL初始化Request,並設定回撥函式。 當該request下載完畢並返回時,將生成response,並作為引數傳給該回調函式。spider中初始的request是通過呼叫

    start_requests() 來獲取的。 start_requests() 讀取 start_urls 中 的URL, 並以 parse 為回撥函式生成 Request

  • 在回撥函式內分析返回的(網頁)內容,返回 Item 物件或者 Request 或者一個包括二者的可迭代容器。 返回的Request物件之後會經過Scrapy處理,下載相應的內容,並呼叫設定的callback函式(函式可相同)。

  • 在回撥函式內,您可以使用 選擇器(Selectors) (您也可以使用BeautifulSoup, lxml 或者您想用的任何解析器) 來分析網頁內容,並根據分析的資料生成item。

  • 最後,由spider返回的item將被存到資料庫(由某些 Item Pipeline 處理)或使用 Feed exports 存入到檔案中。

通過以上幾步的迴圈往復的進行,就可以完成站點的爬取。

二、Spider類分析

scrapy.Spider.[namespider] 例如class JdbraSpider(scrapy.Spider)中JdbraSpider就是namespider的名字,在使用scrapy genspider Jdbra時,會自動建立這樣一個類。Spider並沒有提供什麼特殊的功能。 其僅僅請求給定的 start_urls/start_requests

,並根據返回的結果(resulting responses)呼叫spider的 parse 方法。

2.1 name

定義spider名字的字串(string)。spider的名字定義了Scrapy如何定位(並初始化)spider,所以其必須是唯一的。 不過您可以生成多個相同的spider例項(instance),這沒有任何限制。 name是spider最重要的屬性,而且是必須的。

如果該spider爬取單個網站(single domain),一個常見的做法是以該網站(domain)(加或不加 字尾 )來命名spider。 例如,如果spider爬取 mywebsite.com ,該spider通常會被命名為 mywebsite

2.2 allow_domains

允許爬取的域名,是可選配置,不在此域名範圍的連結,不會被跟進爬取。

2.3 start_urls

URL列表。當沒有制定特定的URL時,spider將從該列表中開始進行爬取。 因此,第一個被獲取到的頁面的URL將是該列表之一。 後續的URL將會從獲取到的資料中提取。

2.4 custom_settings

它是一個字典,是專屬於Spider的配置,此方法會覆蓋全域性的配置,此設定必須在初始化前被更新,必須定義成類變數。

理解的操作方式:

在之前的專案裡面,建立一個知乎的Spider:

在start_urls的連結改成start_urls = ['http://www.zhihu.com/explore']

在settings.py裡面DEFAULT_REQUEST_HEADERS加入user-agent資訊

DEFAULT_REQUEST_HEADERS = {

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',

'Accept-Language': 'en',

'user-agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',

}

先執行下給spider看看有什麼問題:

會看到,返回200的狀態碼:

 

 

在zhihu.py檔案裡面加入custom_settings相關配置:

custom_settings={

'DEFAULT_REQUEST_HEADERS':{

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',

'Accept-Language': 'en',

'user-agent': None,

}

}

在執行zhihu看看有什麼問題:

 

請求時出現了400的狀態碼,說明custom_settings相關配置已經生效,得到了錯誤的響應。

說明custom_settings用來覆蓋settings的全域性配置。

2.5 crawler

它是由from_crawler方法設定的,代表本Spider對應的Crawler物件,包含了許多專案元件。我們可以利用它來獲取專案中的一些配置資訊,最常見的就是從settings.py裡面獲取專案的配置資訊。

2.6 from_crawler()

使用該方法可以獲取Crawler物件裡面的專案元件配置資訊。此方法和Pipeline裡面使用是一樣的。

2.7 start_requests()

此方法用於生成初始請求,它必須必須返回一個可迭代物件。此方法會預設使用start_urls裡面的URL來構建Request,而且Request是以GET方式進行請求。如果我們想在啟動時,想以POST的請求方式訪問某個網站,可以直接重寫這個方法。

理解的操作方式:(http.org是一個進行http請求方式模擬的一個網站)

重新建立一個httpbin的Spider:

原封不動進行執行:

看效果,完成的是get請求:

先對start_urls改成start_urls = ['http://httpbin.org/post']

再執行,出現了以下情況:

 

接下來對start_requests()進行改寫:

def start_requests(self):

yield scrapy.Request(url='http://httpbin.org/post',method='POST',callback=self.parse_post)

def parse(self, response):

pass

def parse_post(self,response):

print('請求成功:',response.status)

再次執行,可以看到如下資訊:

2.8 make_requests_from_url(url)

該方法接受一個URL並返回用於爬取的 Request 物件。 該方法在初始化request時被 start_requests() 呼叫,也被用於轉化url為request。

預設未被複寫(overridden)的情況下,該方法返回的Request物件中, parse() 作為回撥函式,dont_filter引數也被設定為開啟。 (詳情參見 Request)

理解的操作方式:

重新建立一個baidu的Spider:

改寫make_requests_from_url(),改變回調函式:

def make_requests_from_url(self, url):

return scrapy.Request(url=url,callback=self.parse_page)

def parse(self, response):

pass

def parse_page(self,response):

print(response.status)

進行執行:

通過上面該寫可以看到,url直接來走start_urls裡面的元素,還可以直接改變回調函式

如果我們在加入改寫的start_request(),就不會再呼叫make_requests_from_url()方法。

def start_requests(self):

yield scrapy.Request(url='http://www.baidu.com/',callback=self.parse_index)

def parse_index(self,response):

print('呼叫start_resquest()方法')

def make_requests_from_url(self, url):

return scrapy.Request(url=url,callback=self.parse_page)

def parse(self, response):

pass

def parse_page(self,response):

print(response.status)

self.logger.info(response.status)

執行spider之後就會看到如下資訊:

2.9 parse()

當response沒有指定回撥函式時,該方法是Scrapy處理下載的response的預設方法。

parse 負責處理response並返回處理的資料以及(/或)跟進的URL。 Spider 對其他的Request的回撥函式也有相同的要求。

該方法及其他的Request回撥函式必須返回一個包含 Request、dict 或 Item 的可迭代的物件。

2.10 logger()

日誌輸出的方法,有info()和DEBUG()方法,可以輸出日誌的誒輸出資訊:方法見2.8最後一段程式碼。

2.11 close()

當spider關閉時,該函式被呼叫。有一個引數reason,表示當前引數中斷的原因。

def close(self,spider, reason):
print('++++++++++++')
self.logger.debug(reason)