人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動(dòng)態(tài)

Python爬蟲(chóng)進(jìn)階Scrapy框架精文講解

發(fā)布日期:2021-12-21 15:47 | 文章來(lái)源:腳本之家

一、前情提要

為什么要使用Scrapy 框架?

前兩篇深造篇介紹了多線程這個(gè)概念和實(shí)戰(zhàn)
多線程網(wǎng)頁(yè)爬取
多線程爬取網(wǎng)頁(yè)項(xiàng)目實(shí)戰(zhàn)

經(jīng)過(guò)之前的學(xué)習(xí),我們基本掌握了分析頁(yè)面、分析動(dòng)態(tài)請(qǐng)求、抓取內(nèi)容,也學(xué)會(huì)使用多線程來(lái)并發(fā)爬取網(wǎng)頁(yè)提高效率。這些技能點(diǎn)已經(jīng)足夠我們寫(xiě)出各式各樣符合我們要求的爬蟲(chóng)了。
但我們還有一個(gè)沒(méi)解決的問(wèn)題,那就是工程化。工程化可以讓我們寫(xiě)代碼的過(guò)程從「想一段寫(xiě)一段」中解脫出來(lái),變得有秩序、風(fēng)格統(tǒng)一、不寫(xiě)重復(fù)的東西。

而Scrapy 就是爬蟲(chóng)框架中的佼佼者。它為我們提前想好了很多步驟和要處理的邊邊角角的問(wèn)題,而使用者可以專心于處理解析頁(yè)面、分析請(qǐng)求這種最核心的事情。

二、Scrapy框架的概念

Scrapy 是一個(gè)純 Python 實(shí)現(xiàn)的、流行的網(wǎng)絡(luò)爬蟲(chóng)框架,它使用了一些高級(jí)功能來(lái)簡(jiǎn)化網(wǎng)頁(yè)的抓取,能讓我們的爬蟲(chóng)更加的規(guī)范、高效。

它可以分為如下幾個(gè)部分

組件 功能
Scrapy Engine Scrapy 引擎,負(fù)責(zé)控制整個(gè)系統(tǒng)的數(shù)據(jù)流和事件的觸發(fā)
Scheduler 調(diào)度器,接收 Scrapy 引擎發(fā)來(lái)的請(qǐng)求并將其加入隊(duì)列中,等待引擎后續(xù)需要時(shí)使用
Downloader 下載器,爬取網(wǎng)頁(yè)內(nèi)容,將爬取到的數(shù)據(jù)返回給 Spiders(爬蟲(chóng))
Spiders 爬蟲(chóng),這部分是核心代碼,用于解析、提取出需要的數(shù)據(jù)
Item Pipeline 數(shù)據(jù)管道,處理提取出的數(shù)據(jù),主要是數(shù)據(jù)清洗、驗(yàn)證和數(shù)據(jù)存儲(chǔ)
Downloader middlewares 下載器中間件,處理 Scrapy 引擎和下載器之間的請(qǐng)求和響應(yīng)
Spider middlewares 爬蟲(chóng)中間件,處理爬蟲(chóng)輸入的響應(yīng)以及輸出結(jié)果或新的請(qǐng)求

Scrapy 中數(shù)據(jù)流的過(guò)程如下

步驟 數(shù)據(jù)流
1 引擎打開(kāi)一個(gè)網(wǎng)站,找到處理該網(wǎng)站對(duì)應(yīng)的爬蟲(chóng),并爬取網(wǎng)頁(yè)的第一個(gè)頁(yè)面
2 引擎從爬蟲(chóng)中獲取第一個(gè)頁(yè)面地址,并將其作為請(qǐng)求放進(jìn)調(diào)度器中進(jìn)行調(diào)度
3 引擎從調(diào)度器中獲取下一個(gè)頁(yè)面的地址
4 調(diào)度器返回下一個(gè)頁(yè)面的地址給 Scrapy 引擎,Scrapy 引擎通過(guò)下載器中間件傳遞給下載器進(jìn)行爬取
5 爬取到數(shù)據(jù)后,下載器通過(guò)下載器中間件回傳給 Scrapy 引擎
6 Scrapy 引擎將爬取到的數(shù)據(jù)通過(guò)爬蟲(chóng)中間件傳遞給爬蟲(chóng)進(jìn)行數(shù)據(jù)解析、提取
7 爬蟲(chóng)處理完數(shù)據(jù)后,將提取出的數(shù)據(jù)和新的請(qǐng)求回傳給 Scrapy 引擎
8 Scrapy 將提取出的數(shù)據(jù)傳給數(shù)據(jù)管道進(jìn)行數(shù)據(jù)清洗等操作,同時(shí)將新的請(qǐng)求傳遞給調(diào)度器準(zhǔn)備進(jìn)行下一頁(yè)的爬取
9 重復(fù) 2-8 步,直到調(diào)度器中沒(méi)有新的請(qǐng)求,數(shù)據(jù)爬取結(jié)束

三、Scrapy安裝

Win + R打開(kāi)運(yùn)行,點(diǎn)擊確定

然后在命令行上敲上

pip install scrapy -i https://pypi.doubanio.com/simple/
# 這句話后面 -i https://pypi.doubanio.com/simple/ 表示使用豆瓣的源,這樣安裝會(huì)更快

之后點(diǎn)擊回車,等待它自己安裝完成便可!

然后,我們?cè)诿钚猩锨蒙?mark>scrapy,便會(huì)顯示scrapy的信息,這樣就代表安裝成功啦!

注意!!再然后我們?cè)诿钚星蒙?explorer . (Mac 中是 open .,注意 . 前面有個(gè)空格) 命令并回車,可以打開(kāi)命令行當(dāng)前所在的目錄。下面,我們就要在這個(gè)目錄里開(kāi)始編寫(xiě)代碼。

四、Scrapy實(shí)戰(zhàn)運(yùn)用

這次我們?cè)囍肧crapy爬取的網(wǎng)站是:小眾軟件 https://www.appinn.com/category/windows/

在進(jìn)行網(wǎng)頁(yè)爬取前,我們先需要?jiǎng)?chuàng)建代碼文件,然后利用Scrapy命令進(jìn)行執(zhí)行。

在上面我們利用 explorer . 命令打開(kāi)了目錄,在這個(gè)目錄下我們創(chuàng)建一個(gè) spider.py 的文件↓
方法:創(chuàng)建文本文件改后綴名即可

然后將爬蟲(chóng)代碼放進(jìn)去,現(xiàn)在大家先復(fù)制黏貼代碼,進(jìn)行嘗試一下,之后我再來(lái)講解代碼的含義!

爬蟲(chóng)代碼

import scrapy
# 定義一個(gè)類叫做 TitleSpider 繼承自 scrapy.Spider
class TitleSpider(scrapy.Spider):
 name = 'title-spider'
 # 設(shè)定開(kāi)始爬取的頁(yè)面
 start_urls = ['https://www.appinn.com/category/windows/']
 def parse(self, response):
  # 找到所有 article 標(biāo)簽
  for article in response.css('article'):
# 解析 article 下面 a 標(biāo)簽里的鏈接和標(biāo)題
a = article.css('h2.title a')
if a:
 result = {
  'title': a.attrib['title'],
  'url': a.attrib['href'],
 }
 # 得到結(jié)果
 yield result
  # 解析下一頁(yè)的鏈接
  next_page = response.css('a.next::attr(href)').get()
  if next_page is not None:
# 開(kāi)始爬下一頁(yè),使用 parse 方法解析
yield response.follow(next_page, self.parse)

然后在命令行中執(zhí)行 scrapy 的 runspider 命令

scrapy runspider spider.py -t csv -o apps.csv
# spider.py 是剛剛寫(xiě)的爬蟲(chóng)代碼的文件名
# -t 表示輸出的文件格式,我們用 csv,方便用 Excel 等工具打開(kāi)
# -o 表示輸出的文件名,所以執(zhí)行完會(huì)出現(xiàn)一個(gè) apps.csv 的文件

敲完上面這句命令,稍等一下,你應(yīng)該能看見(jiàn)很多的輸出👇

網(wǎng)頁(yè)爬取結(jié)果

以及目錄里多出來(lái)一個(gè) apps.csv 文件。有 Excel 的同學(xué)可以用 Excel 打開(kāi) apps.csv,或者直接用記事本或者其他編輯器打開(kāi)它。

打開(kāi)后能看見(jiàn) 400 多篇小眾軟件的軟件推薦文章的標(biāo)題和鏈接👇


可是我們的代碼里完全沒(méi)有用到 requests、beautifulsoup、concurrent 以及文件相關(guān)的庫(kù),是怎么完成了一次快速的爬取并寫(xiě)到文件的呢?別急,讓我為你慢慢講解!

這一串代碼干了什么?

上面用到的爬蟲(chóng)代碼

import scrapy
# 定義一個(gè)類叫做 TitleSpider 繼承自 scrapy.Spider
class TitleSpider(scrapy.Spider):
 name = 'title-spider'
 # 設(shè)定開(kāi)始爬取的頁(yè)面
 start_urls = ['https://www.appinn.com/category/windows/']
 def parse(self, response):
  # 找到所有 article 標(biāo)簽
  for article in response.css('article'):
# 解析 article 下面 a 標(biāo)簽里的鏈接和標(biāo)題
a = article.css('h2.title a')
if a:
 result = {
  'title': a.attrib['title'],
  'url': a.attrib['href'],
 }
 # 得到結(jié)果
 yield result
  # 解析下一頁(yè)的鏈接
  next_page = response.css('a.next::attr(href)').get()
  if next_page is not None:
# 開(kāi)始爬下一頁(yè),使用 parse 方法解析
yield response.follow(next_page, self.parse)

當(dāng)運(yùn)行scrapy runspider spider.py -t csv -o apps.csv時(shí),Scrapy 會(huì)執(zhí)行我們寫(xiě)在 spider.py里的爬蟲(chóng),也就是上面那段完整的代碼

1、首先,Scrapy 讀到我們?cè)O(shè)定的啟動(dòng)頁(yè)面 start_urls,開(kāi)始請(qǐng)求這個(gè)頁(yè)面,得到一個(gè)響應(yīng)。

// An highlighted block
start_urls = ['https://www.appinn.com/category/windows/']

2、之后,Scrapy 把這個(gè)響應(yīng)交給 默認(rèn) 的解析方法 parse 來(lái)處理。響應(yīng) response 就是 parse 的第一個(gè)參數(shù)

def parse(self, response):

3、在我們自己寫(xiě)的 parse 方法里,有兩個(gè)部分:一是解析出頁(yè)面里的 article 標(biāo)簽,得到標(biāo)題和鏈接作為爬取的結(jié)果;二是解析 下一頁(yè) 按鈕這個(gè)位置,拿到下一頁(yè)的鏈接,并同樣繼續(xù)請(qǐng)求、然后使用 parse 方法解析

# 把這條結(jié)果告訴 Scrapy
yield result
# 通知 Scrapy 開(kāi)始爬下一頁(yè),使用 parse 方法解析
yield response.follow(next_page, self.parse)

yield 是 Python 中一個(gè)較高級(jí)的用法,在這里我們只需要知道,我們通過(guò) yield 通知 Scrapy 兩件事:我們拿到了結(jié)果,快去處理吧、我們拿到了下一個(gè)要爬的鏈接,快去爬取吧。

流程圖


沒(méi)錯(cuò),除了解析想要的數(shù)據(jù),其他的一切都是 Scrapy 替你完成的。這就是 Scrapy 的最大優(yōu)勢(shì):
requests 去哪了?不需要,只要把鏈接交給 Scrapy 就會(huì)自動(dòng)幫你完成請(qǐng)求;
concurrent 去哪了?不需要,Scrapy 會(huì)自動(dòng)把全部的請(qǐng)求都變成并發(fā)的;
怎么把結(jié)果寫(xiě)到文件?不用實(shí)現(xiàn)寫(xiě)文件的代碼,使用 yield 通知一下 Scrapy 結(jié)果即可自動(dòng)寫(xiě)入文件;
怎么繼續(xù)爬取下一個(gè)頁(yè)面?使用 yield 通知 =Scrapy下一個(gè)頁(yè)面的鏈接和處理方法就好;
BeautifulSoup 去哪了?可以不需要,Scrapy 提供了好用的 CSS 選擇器。

解析數(shù)據(jù)這件事情還是值得我們關(guān)心的,即使 Scrapy 沒(méi)有強(qiáng)制讓我們使用什么,因此我們非要繼續(xù)使用 BeautifulSoup也是可以的,只需在 parse() 方法里將 response.text 傳遞給 BeautifulSoup 進(jìn)行解析、提取即可。

但是 Scrapy 提供了很好用的工具,叫做 CSS 選擇器。CSS 選擇器我們?cè)?BeautifulSoup 中簡(jiǎn)單介紹過(guò),你還有印象嗎?

對(duì)BeautifulSoup這個(gè)庫(kù)忘記了的同學(xué),可以看看我之前寫(xiě)的一篇文章:requests庫(kù)和BeautifulSoup庫(kù)

Scrapy 中的 CSS 選擇器語(yǔ)法和 BeautifulSoup 中的差不多,Scrapy 中的 CSS 選擇器更加強(qiáng)大一些

# 從響應(yīng)里解析出所有 article 標(biāo)簽
response.css('article')
# 從 article 里解析出 class 為 title 的 h2 標(biāo)簽 下面的 a 標(biāo)簽
article.css('h2.title a')
# 取出 a 里面的 href 屬性值
a.attrib['href']
# 從響應(yīng)里解析出 class 為 next 的 a 標(biāo)簽的 href 屬性,并取出它的值
response.css('a.next::attr(href)').get()

scrapy 中的 CSS 選擇器可以取代 beautifulsoup 的功能,我們直接用它就解析、提取獲取到的數(shù)據(jù)??吹竭@里,再回頭看上面的完整代碼,試著結(jié)合流程圖再理解一下就會(huì)有不錯(cuò)的了解了。

五、Scrapy的css選擇器教學(xué)

我們還是打開(kāi)之前爬取的網(wǎng)站:小眾軟件 https://www.appinn.com/category/windows/
用網(wǎng)頁(yè)開(kāi)發(fā)者工具選中 下一頁(yè)↓

注意截圖中被框住的部分,瀏覽器已經(jīng)展示出來(lái)這個(gè)按鈕的 CSS 選擇方法是什么了。它告訴我們下一頁(yè)按鈕的選擇方式是a.next.page-numbers。

開(kāi)始css選擇器教學(xué)前,我建議你使用 Scrapy 提供的互動(dòng)工具來(lái)體驗(yàn)一下 CSS 選擇器。方式是在命令行中輸入以下命令并回車

scrapy shell "https://www.appinn.com/category/windows/"

這時(shí) Scrapy 已經(jīng)訪問(wèn)了這個(gè)鏈接,并把獲取到的結(jié)果記錄了下來(lái),你會(huì)進(jìn)入到一個(gè)交互環(huán)境,我們可以在這個(gè)環(huán)境里寫(xiě)代碼并一句一句執(zhí)行。輸入 response 并回車,你能看見(jiàn)類似下面的響應(yīng),這就是上面獲取到的網(wǎng)頁(yè)結(jié)果。

我之前有說(shuō)過(guò),輸出的200其實(shí)就是一個(gè)響應(yīng)狀態(tài)碼,意思就是請(qǐng)求成功了!
之前的文章:requests庫(kù)和BeautifulSoup庫(kù)

下面我們就來(lái)學(xué)習(xí)一下css選擇器吧,我們以下圖中“下一頁(yè)”按鈕為例子👇

按標(biāo)簽名選擇

小眾軟件網(wǎng)站下一頁(yè)按鈕的選擇方式是 a.next.page-numbers,其中的 a 是標(biāo)簽名。試著在互動(dòng)環(huán)境中,輸入 response.css(‘a(chǎn)'),可以看到頁(yè)面上所有的 a 元素。其他元素也是一樣,例如寫(xiě) response.css(‘ul') 就可以選擇出所有 ul 元素,response.css(‘div') 可以選擇出 div 元素。

按 class 選擇

a.next.page-numbers 中的.next 和 .page-numbers 表示 class的名字。當(dāng)我們想要選擇 class 包含 container 的 div 元素,我們可以寫(xiě)response.css(‘div.container')。

上面的選擇器前面是標(biāo)簽名,. 表示 class,后面跟著 class 的名稱。注意,它們是緊緊挨在一起的,中間不能有空格!

當(dāng)要選擇的元素有多個(gè) class 時(shí),比如下面這樣的一個(gè)元素

<a class="next page-numbers" href="/windows/page/2/" rel="external nofollow">下一頁(yè)</a>

這個(gè) a 元素有 next 和 page-number 兩個(gè) class,可以寫(xiě)多個(gè) . 來(lái)選擇:response.css(‘a(chǎn).next.page-numbers')。表示選擇 class 同時(shí)包含 next 和 page-numbers 的 a 元素,這里它們也必須緊挨在一起,之前不能有空格。

按 id 選擇

除了 class 選擇器外,同樣也有 id 選擇器,Scrapy 中也是用 # 代表 id。比如網(wǎng)頁(yè)上的菜單按鈕,我們看到它的 id 是 pull,class 是 toggle-mobile-menu。所以可以寫(xiě) response.css(‘a(chǎn)#pull'),表示我們想選擇一個(gè) id 為 pull 的 a 元素。

當(dāng)然,你也可以組合使用:response.css(‘a(chǎn)#pull.toggle-mobile-menu')。表示我們要選擇 id 為 pull,并且 class 包含 toggle-mobile-menu 的 a 元素。

按層級(jí)關(guān)系選擇

還是小眾軟件的這個(gè)頁(yè)面,如果我們想用 CSS 選擇器選中標(biāo)題這個(gè)位置的 a 元素,使用 Chrome 選取之后發(fā)現(xiàn)這個(gè) a 元素既沒(méi)有 id 也沒(méi)有 class,瀏覽器也只給我們提示一個(gè) a👇

這時(shí),我們就需要在該元素的父元素上找找線索,例如我們發(fā)現(xiàn)這個(gè) a 元素在一個(gè) h2 元素的下面,而這個(gè) h2 元素是有 class 的,class 為 title 和 post-title。所以我們要做的是選擇 class 為 title 和 post-title 的 h2 元素下面的 a 元素,用 CSS 選擇器寫(xiě)作

response.css('h2.title.post-title a::text')

可以看到,title 和 post-title 的 h2 元素寫(xiě)作 h2.title.post-title,是緊緊連在一起的,而下面的 a 元素則在 a 前面加了一個(gè)空格。想起之前說(shuō)過(guò)的規(guī)則了嗎?規(guī)則便是:并列關(guān)系連在一起,層級(jí)關(guān)系用空格隔開(kāi)。

.title 和 .post-title 緊跟在 h2 后面,它倆都是 h2 的篩選條件。而空格后面跟著的 a 表示符合 h2.title.post-title 條件元素的子元素中的所有 a 元素。

我們之前還說(shuō)過(guò),空格后面表示的是所有的子元素,不管是處于多少層的子元素。而如果只想要第一層的子元素則應(yīng)該用 > 分隔開(kāi)。這里的 a 元素就是第一層的子元素,所以 h2.title.post-title a 和 h2.title.post-title > a 這兩種寫(xiě)法的效果是一樣的。

取元素中的文本

我們拿到了標(biāo)題位置的 a 元素,想要拿到其中的文本內(nèi)容就需要在后面加上 ::text,代碼如下

response.css('h2.title.post-title a::text')

在互動(dòng)環(huán)境執(zhí)行一下,會(huì)發(fā)現(xiàn)文本內(nèi)容能獲取到,但不是我們想要的純文本,如果想拿到純文本,還需要使用 get() 或者 getall() 方法,如下

# 取符合條件的第一條數(shù)據(jù)
response.css('h2.title.post-title a::text').get()
# 取符合條件的所有數(shù)據(jù)
response.css('h2.title.post-title a::text').getall()

取元素的屬性

還是用這個(gè) a 元素舉例。如果我們想得到這個(gè) a 元素的 href 屬性,需要調(diào)用這個(gè)元素的 attrib 屬性。在互動(dòng)環(huán)境中執(zhí)行下面兩句代碼

# 拿到符合選擇器條件的第一個(gè) a 標(biāo)簽
a = response.css('h2.title.post-title a')
a.attrib['href']

attrib 屬性實(shí)際上是一個(gè)字典,里面存儲(chǔ)了元素上的所有 HTML 屬性。如果把第二句換成 a.attrib,你就能看到這個(gè) a 元素上的所有屬性。類似的,輸入 a.attrib[‘title'],你可以得到它的 title 屬性。

現(xiàn)在我們?cè)囋嚧蛴∷蟹?h2.title.post-title a 這個(gè)條件的標(biāo)簽的 href 屬性,就像下面這樣

for a in response.css('h2.title.post-title a'):
  print(a.attrib['href'])

或者另一種寫(xiě)法也可以取到 href 屬性,就是加上 ::attr(href)

for href in response.css('h2.title.post-title a::attr(href)').getall():
  print(href)

本次分享到此結(jié)束了,非常感謝大家閱讀!!
有問(wèn)題歡迎評(píng)論區(qū)留言?。?/p>

以上就是Python爬蟲(chóng)進(jìn)階Scrapy框架精文講解的詳細(xì)內(nèi)容,更多關(guān)于Python爬蟲(chóng)Scrapy框架的資料請(qǐng)關(guān)注本站其它相關(guān)文章!

版權(quán)聲明:本站文章來(lái)源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來(lái)源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來(lái)源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來(lái),僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。

相關(guān)文章

實(shí)時(shí)開(kāi)通

自選配置、實(shí)時(shí)開(kāi)通

免備案

全球線路精選!

全天候客戶服務(wù)

7x24全年不間斷在線

專屬顧問(wèn)服務(wù)

1對(duì)1客戶咨詢顧問(wèn)

在線
客服

在線客服:7*24小時(shí)在線

客服
熱線

400-630-3752
7*24小時(shí)客服服務(wù)熱線

關(guān)注
微信

關(guān)注官方微信
頂部