小編給大家分享一下關(guān)于Python3爬蟲中Selector的用法,相信大部分人都還不怎么了解,因此分享這篇文章給大家學(xué)習(xí),希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去學(xué)習(xí)方法吧!
創(chuàng)新互聯(lián)建站網(wǎng)站建設(shè)公司,提供成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作,網(wǎng)頁設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);可快速的進(jìn)行網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,是專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!
Selector 的用法
我們之前介紹了利用 Beautiful Soup、pyquery 以及正則表達(dá)式來提取網(wǎng)頁數(shù)據(jù),這確實(shí)非常方便。而 Scrapy 還提供了自己的數(shù)據(jù)提取方法,即 Selector(選擇器)。Selector 是基于 lxml 來構(gòu)建的,支持 XPath 選擇器、CSS 選擇器以及正則表達(dá)式,功能全面,解析速度和準(zhǔn)確度非常高。
本節(jié)將介紹 Selector 的用法。
1. 直接使用
Selector 是一個(gè)可以獨(dú)立使用的模塊。我們可以直接利用 Selector 這個(gè)類來構(gòu)建一個(gè)選擇器對(duì)象,然后調(diào)用它的相關(guān)方法如 xpath()、css() 等來提取數(shù)據(jù)。
例如,針對(duì)一段 HTML 代碼,我們可以用如下方式構(gòu)建 Selector 對(duì)象來提取數(shù)據(jù):
from scrapy import Selector body = 'Hello World ' selector = Selector(text=body) title = selector.xpath('//title/text()').extract_first() print(title)
運(yùn)行結(jié)果:
Hello World
我們?cè)谶@里沒有在 Scrapy 框架中運(yùn)行,而是把 Scrapy 中的 Selector 單獨(dú)拿出來使用了,構(gòu)建的時(shí)候傳入 text 參數(shù),就生成了一個(gè) Selector 選擇器對(duì)象,然后就可以像前面我們所用的 Scrapy 中的解析方式一樣,調(diào)用 xpath()、css() 等方法來提取了。
在這里我們查找的是源代碼中的 title 中的文本,在 XPath 選擇器最后加 text() 方法就可以實(shí)現(xiàn)文本的提取了。
以上內(nèi)容就是 Selector 的直接使用方式。同 Beautiful Soup 等庫(kù)類似,Selector 其實(shí)也是強(qiáng)大的網(wǎng)頁解析庫(kù)。如果方便的話,我們也可以在其他項(xiàng)目中直接使用 Selector 來提取數(shù)據(jù)。
接下來,我們用實(shí)例來詳細(xì)講解 Selector 的用法。
2. Scrapy Shell
由于 Selector 主要是與 Scrapy 結(jié)合使用,如 Scrapy 的回調(diào)函數(shù)中的參數(shù) response 直接調(diào)用 xpath() 或者 css() 方法來提取數(shù)據(jù),所以在這里我們借助 Scrapy shell 來模擬 Scrapy 請(qǐng)求的過程,來講解相關(guān)的提取方法。
我們用官方文檔的一個(gè)樣例頁面來做演示:http://doc.scrapy.org/en/latest/_static/selectors-sample1.html。
開啟 Scrapy shell,在命令行輸入如下命令:
scrapy shell http://doc.scrapy.org/en/latest/_static/selectors-sample1.html
我們就進(jìn)入到 Scrapy shell 模式。這個(gè)過程其實(shí)是,Scrapy 發(fā)起了一次請(qǐng)求,請(qǐng)求的 URL 就是剛才命令行下輸入的 URL,然后把一些可操作的變量傳遞給我們,如 request、response 等,如圖 13-5 所示。
圖 13-5 Scrapy Shell
我們可以在命令行模式下輸入命令調(diào)用對(duì)象的一些操作方法,回車之后實(shí)時(shí)顯示結(jié)果。這與 Python 的命令行交互模式是類似的。
接下來,演示的實(shí)例都將頁面的源碼作為分析目標(biāo),頁面源碼如下所示:
Example website
3. XPath 選擇器
進(jìn)入 Scrapy shell 之后,我們將主要操作 response 這個(gè)變量來進(jìn)行解析。因?yàn)槲覀兘馕龅氖?HTML 代碼,Selector 將自動(dòng)使用 HTML 語法來分析。
response 有一個(gè)屬性 selector,我們調(diào)用 response.selector 返回的內(nèi)容就相當(dāng)于用 response 的 text 構(gòu)造了一個(gè) Selector 對(duì)象。通過這個(gè) Selector 對(duì)象我們可以調(diào)用解析方法如 xpath()、css() 等,通過向方法傳入 XPath 或 CSS 選擇器參數(shù)就可以實(shí)現(xiàn)信息的提取。
我們用一個(gè)實(shí)例感受一下,如下所示:
>>> result = response.selector.xpath('//a') >>> result [Name: My image 1 <'>, Name: My image 2 <'>, Name: My image 3 <'>, Name: My image 4 <'>, Name: My image 5 <'>] >>> type(result) scrapy.selector.unified.SelectorList
打印結(jié)果的形式是 Selector 組成的列表,其實(shí)它是 SelectorList 類型,SelectorList 和 Selector 都可以繼續(xù)調(diào)用 xpath() 和 css() 等方法來進(jìn)一步提取數(shù)據(jù)。
在上面的例子中,我們提取了 a 節(jié)點(diǎn)。接下來,我們嘗試?yán)^續(xù)調(diào)用 xpath() 方法來提取 a 節(jié)點(diǎn)內(nèi)包含的 img 節(jié)點(diǎn),如下所示:
>>> result.xpath('./img') ['>, '>, '>, '>, '>]
我們獲得了 a 節(jié)點(diǎn)里面的所有 img 節(jié)點(diǎn),結(jié)果為 5。
值得注意的是,選擇器的最前方加 .(點(diǎn)),這代表提取元素內(nèi)部的數(shù)據(jù),如果沒有加點(diǎn),則代表從根節(jié)點(diǎn)開始提取。此處我們用了./img 的提取方式,則代表從 a 節(jié)點(diǎn)里進(jìn)行提取。如果此處我們用 //img,則還是從 html 節(jié)點(diǎn)里進(jìn)行提取。
我們剛才使用了 response.selector.xpath() 方法對(duì)數(shù)據(jù)進(jìn)行了提取。Scrapy 提供了兩個(gè)實(shí)用的快捷方法,response.xpath() 和 response.css(),它們二者的功能完全等同于 response.selector.xpath() 和 response.selector.css()。方便起見,后面我們統(tǒng)一直接調(diào)用 response 的 xpath() 和 css() 方法進(jìn)行選擇。
現(xiàn)在我們得到的是 SelectorList 類型的變量,該變量是由 Selector 對(duì)象組成的列表。我們可以用索引單獨(dú)取出其中某個(gè) Selector 元素,如下所示:
>>> result[0]Name: My image 1 <'>
我們可以像操作列表一樣操作這個(gè) SelectorList。
但是現(xiàn)在獲取的內(nèi)容是 Selector 或者 SelectorList 類型,并不是真正的文本內(nèi)容。那么具體的內(nèi)容怎么提取呢?
比如我們現(xiàn)在想提取出 a 節(jié)點(diǎn)元素,就可以利用 extract() 方法,如下所示:
>>> result.extract() ['Name: My image 1
', 'Name: My image 2
', 'Name: My image 3
', 'Name: My image 4
', 'Name: My image 5
']
這里使用了 extract() 方法,我們就可以把真實(shí)需要的內(nèi)容獲取下來。
我們還可以改寫 XPath 表達(dá)式,來選取節(jié)點(diǎn)的內(nèi)部文本和屬性,如下所示:
>>> response.xpath('//a/text()').extract() ['Name: My image 1 ', 'Name: My image 2 ', 'Name: My image 3 ', 'Name: My image 4 ', 'Name: My image 5 '] >>> response.xpath('//a/@href').extract() ['image1.html', 'image2.html', 'image3.html', 'image4.html', 'image5.html']
我們只需要再加一層 /text() 就可以獲取節(jié)點(diǎn)的內(nèi)部文本,或者加一層 /@href 就可以獲取節(jié)點(diǎn)的 href 屬性。其中,@符號(hào)后面內(nèi)容就是要獲取的屬性名稱。
現(xiàn)在我們可以用一個(gè)規(guī)則把所有符合要求的節(jié)點(diǎn)都獲取下來,返回的類型是列表類型。
但是這里有一個(gè)問題:如果符合要求的節(jié)點(diǎn)只有一個(gè),那么返回的結(jié)果會(huì)是什么呢?我們?cè)儆靡粋€(gè)實(shí)例來感受一下,如下所示:
>>> response.xpath('//a[@href="image1.html"]/text()').extract() ['Name: My image 1 ']
我們用屬性限制了匹配的范圍,使 XPath 只可以匹配到一個(gè)元素。然后用 extract() 方法提取結(jié)果,其結(jié)果還是一個(gè)列表形式,其文本是列表的第一個(gè)元素。但很多情況下,我們其實(shí)想要的數(shù)據(jù)就是第一個(gè)元素內(nèi)容,這里我們通過加一個(gè)索引來獲取,如下所示:
python>>> response.xpath('//a[@href="image1.html"]/text()').extract()[0] 'Name: My image 1 '
但是,這個(gè)寫法很明顯是有風(fēng)險(xiǎn)的。一旦 XPath 有問題,那么 extract() 后的結(jié)果可能是一個(gè)空列表。如果我們?cè)儆盟饕齺慝@取, 那不就會(huì)可能導(dǎo)致數(shù)組越界嗎? 所以,另外一個(gè)方法可以專門提取單個(gè)元素,它叫作 extract_first()。我們可以改寫上面的例子如下所示: ```python >>> response.xpath('//a[@href="image1.html"]/text()').extract_first() 'Name: My image 1 '
這樣,我們直接利用 extract_first() 方法將匹配的第一個(gè)結(jié)果提取出來,同時(shí)我們也不用擔(dān)心數(shù)組越界的問題。
另外我們也可以為 extract_first() 方法設(shè)置一個(gè)默認(rèn)值參數(shù),這樣當(dāng) XPath 規(guī)則提取不到內(nèi)容時(shí)會(huì)直接使用默認(rèn)值。例如將 XPath 改成一個(gè)不存在的規(guī)則,重新執(zhí)行代碼,如下所示:
>>> response.xpath('//a[@href="image1"]/text()').extract_first()>>> response.xpath('//a[@href="image1"]/text()'). extract_first('Default Image') 'Default Image'
這里,如果 XPath 匹配不到任何元素,調(diào)用 extract_first() 會(huì)返回空,也不會(huì)報(bào)錯(cuò)。
在第二行代碼中,我們還傳遞了一個(gè)參數(shù)當(dāng)作默認(rèn)值,如 Default Image。這樣如果 XPath 匹配不到結(jié)果的話,返回值會(huì)使用這個(gè)參數(shù)來代替,可以看到輸出正是如此。
現(xiàn)在為止,我們了解了 Scrapy 中的 XPath 的相關(guān)用法,包括嵌套查詢、提取內(nèi)容、提取單個(gè)內(nèi)容、獲取文本和屬性等。
4. CSS 選擇器
接下來,我們看看 CSS 選擇器的用法。
Scrapy 的選擇器同時(shí)還對(duì)接了 CSS 選擇器,使用 response.css() 方法可以使用 CSS 選擇器來選擇對(duì)應(yīng)的元素。
例如在上文我們選取了所有的 a 節(jié)點(diǎn),那么 CSS 選擇器同樣可以做到,如下所示:
>>> response.css('a') [Name: My image 1 <'>, Name: My image 2 <'>, Name: My image 3 <'>, Name: My image 4 <'>, Name: My image 5 <'>]
同樣,調(diào)用 extract() 方法就可以提取出節(jié)點(diǎn),如下所示:
python>>> response.css(‘a(chǎn)’).extract() [‘Name: My image 1 ‘, ‘Name: My image 2 ‘, ‘Name: My image 3 ‘, ‘Name: My image 4 ‘, ‘Name: My image 5 ‘]
用法和 XPath 選擇是完全一樣的。 另外,我們也可以進(jìn)行屬性選擇和嵌套選擇,如下所示: ```python >>> response.css('a[href="image1.html"]').extract() ['Name: My image 1
'] >>> response.css('a[href="image1.html"] img').extract() [''] ```這里用 [href="image.html"] 限定了 href 屬性,可以看到匹配結(jié)果就只有一個(gè)了。另外如果想查找 a 節(jié)點(diǎn)內(nèi)的 img 節(jié)點(diǎn), 只需要再加一個(gè)空格和 img 即可。選擇器的寫法和標(biāo)準(zhǔn) CSS 選擇器寫法如出一轍。 我們也可以使用 extract_first() 方法提取列表的第一個(gè)元素,如下所示: ```python >>> response.css('a[href="image1.html"] img').extract_first() ''
接下來的兩個(gè)用法不太一樣。節(jié)點(diǎn)的內(nèi)部文本和屬性的獲取是這樣實(shí)現(xiàn)的,如下所示:
>>> response.css('a[href="image1.html"]::text').extract_first() 'Name: My image 1 ' >>> response.css('a[href="image1.html"] img::attr(src)').extract_first() 'image1_thumb.jpg'
獲取文本和屬性需要用::text 和::attr() 的寫法。而其他庫(kù)如 Beautiful Soup 或 pyquery 都有單獨(dú)的方法。
另外,CSS 選擇器和 XPath 選擇器一樣可以嵌套選擇。我們可以先用 XPath 選擇器選中所有 a 節(jié)點(diǎn),再利用 CSS 選擇器選中 img 節(jié)點(diǎn),再用 XPath 選擇器獲取屬性。我們用一個(gè)實(shí)例來感受一下,如下所示:
>>> response.xpath('//a').css('img').xpath('@src').extract() ['image1_thumb.jpg', 'image2_thumb.jpg', 'image3_thumb.jpg', 'image4_thumb.jpg', 'image5_thumb.jpg']
我們成功獲取了所有 img 節(jié)點(diǎn)的 src 屬性。
因此,我們可以隨意使用 xpath() 和 css() 方法二者自由組合實(shí)現(xiàn)嵌套查詢,二者是完全兼容的。
5. 正則匹配
Scrapy 的選擇器還支持正則匹配。比如,在示例的 a 節(jié)點(diǎn)中的文本類似于 Name: My image 1,現(xiàn)在我們只想把 Name: 后面的內(nèi)容提取出來,這時(shí)就可以借助 re() 方法,實(shí)現(xiàn)如下:
>>> response.xpath('//a/text()').re('Name:s(.*)') ['My image 1 ', 'My image 2 ', 'My image 3 ', 'My image 4 ', 'My image 5 ']
我們給 re() 方法傳了一個(gè)正則表達(dá)式,其中 (.*) 就是要匹配的內(nèi)容,輸出的結(jié)果就是正則表達(dá)式匹配的分組,結(jié)果會(huì)依次輸出。
如果同時(shí)存在兩個(gè)分組,那么結(jié)果依然會(huì)被按序輸出,如下所示:
>>> response.xpath('//a/text()').re('(.*?):s(.*)') ['Name', 'My image 1 ', 'Name', 'My image 2 ', 'Name', 'My image 3 ', 'Name', 'My image 4 ', 'Name', 'My image 5 ']
類似 extract_first() 方法,re_first() 方法可以選取列表的第一個(gè)元素,用法如下:
>>> response.xpath('//a/text()').re_first('(.*?):s(.*)') 'Name' >>> response.xpath('//a/text()').re_first('Name:s(.*)') 'My image 1'
不論正則匹配了幾個(gè)分組,結(jié)果都會(huì)等于列表的第一個(gè)元素。
值得注意的是,response 對(duì)象不能直接調(diào)用 re() 和 re_first() 方法。如果想要對(duì)全文進(jìn)行正則匹配,可以先調(diào)用 xpath() 方法再正則匹配,如下所示:
>>> response.re('Name:s(.*)') Traceback (most recent call last): File "", line 1, in AttributeError: 'HtmlResponse' object has no attribute 're' >>> response.xpath('.').re('Name:s(.*)
') ['My image 1 ', 'My image 2 ', 'My image 3 ', 'My image 4 ', 'My image 5 '] >>> response.xpath('.').re_first('Name:s(.*)
') 'My image 1'
通過上面的例子,我們可以看到,直接調(diào)用 re() 方法會(huì)提示沒有 re 屬性。但是這里首先調(diào)用了 xpath(‘.’) 選中全文,然后調(diào)用 re() 和 re_first() 方法,就可以進(jìn)行正則匹配了。
以上是關(guān)于Python3爬蟲中Selector的用法的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!