欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時(shí)間:2021年10月21日 16:41:50   作者:HuiSoul  
這篇文章主要為大家介紹了Python爬蟲進(jìn)階中Scrapy框架精細(xì)講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步

一、前情提要

為什么要使用Scrapy 框架?

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

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

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

二、Scrapy框架的概念

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

在這里插入圖片描述

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

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

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

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

三、Scrapy安裝

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

在這里插入圖片描述

然后在命令行上敲上

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

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

在這里插入圖片描述

然后,我們在命令行上敲上scrapy,便會(huì)顯示scrapy的信息,這樣就代表安裝成功啦!

在這里插入圖片描述

注意?。≡偃缓笪覀冊诿钚星蒙?explorer . (Mac 中是 open .,注意 . 前面有個(gè)空格) 命令并回車,可以打開命令行當(dāng)前所在的目錄。下面,我們就要在這個(gè)目錄里開始編寫代碼。

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

這次我們試著用Scrapy爬取的網(wǎng)站是:小眾軟件 https://www.appinn.com/category/windows/

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

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

在這里插入圖片描述

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

在這里插入圖片描述

爬蟲代碼

import scrapy
# 定義一個(gè)類叫做 TitleSpider 繼承自 scrapy.Spider
class TitleSpider(scrapy.Spider):
    name = 'title-spider'
    # 設(shè)定開始爬取的頁面
    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
        # 解析下一頁的鏈接
        next_page = response.css('a.next::attr(href)').get()
        if next_page is not None:
            # 開始爬下一頁,使用 parse 方法解析
            yield response.follow(next_page, self.parse)

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

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

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

在這里插入圖片描述

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

在這里插入圖片描述

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

在這里插入圖片描述

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

在這里插入圖片描述

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

這一串代碼干了什么?

上面用到的爬蟲代碼

import scrapy
# 定義一個(gè)類叫做 TitleSpider 繼承自 scrapy.Spider
class TitleSpider(scrapy.Spider):
    name = 'title-spider'
    # 設(shè)定開始爬取的頁面
    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
        # 解析下一頁的鏈接
        next_page = response.css('a.next::attr(href)').get()
        if next_page is not None:
            # 開始爬下一頁,使用 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í)行我們寫在 spider.py里的爬蟲,也就是上面那段完整的代碼

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

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

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

def parse(self, response):

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

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

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

流程圖

在這里插入圖片描述

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

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

但是 Scrapy 提供了很好用的工具,叫做 CSS 選擇器。CSS 選擇器我們在 BeautifulSoup 中簡單介紹過,你還有印象嗎?

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

Scrapy 中的 CSS 選擇器語法和 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é)

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

在這里插入圖片描述

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

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

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

在這里插入圖片描述

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

在這里插入圖片描述

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

在這里插入圖片描述

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

在這里插入圖片描述

在這里插入圖片描述

按標(biāo)簽名選擇

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

按 class 選擇

a.next.page-numbers 中的.next 和 .page-numbers 表示 class的名字。當(dāng)我們想要選擇 class 包含 container 的 div 元素,我們可以寫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"   >下一頁</a>

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

按 id 選擇

除了 class 選擇器外,同樣也有 id 選擇器,Scrapy 中也是用 # 代表 id。比如網(wǎng)頁上的菜單按鈕,我們看到它的 id 是 pull,class 是 toggle-mobile-menu。所以可以寫 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 元素。

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

還是小眾軟件的這個(gè)頁面,如果我們想用 CSS 選擇器選中標(biāo)題這個(gè)位置的 a 元素,使用 Chrome 選取之后發(fā)現(xiàn)這個(gè) a 元素既沒有 id 也沒有 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 選擇器寫作

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

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

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

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

取元素中的文本

我們拿到了標(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)在我們試試打印所有符合 h2.title.post-title a 這個(gè)條件的標(biāo)簽的 href 屬性,就像下面這樣

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

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

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

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

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

相關(guān)文章

最新評論