Scrapy學(xué)習(xí)篇(六)之選擇器

當(dāng)我們?nèi)〉昧司W(wǎng)頁的response之后,最關(guān)鍵的就是如何從繁雜的網(wǎng)頁中把我們需要的數(shù)據(jù)提取出來,python從網(wǎng)頁中提取數(shù)據(jù)的包很多,常用的有下面的幾個:

  • BeautifulSoup
    它基于HTML代碼的結(jié)構(gòu)來構(gòu)造一個Python對象, 對不良標(biāo)記的處理也非常合理,但是速度上有所欠缺。
  • lxml
    是一個基于 ElementTree (不是Python標(biāo)準庫的一部分)的python化的XML解析庫(也可以解析HTML)。

你可以在scrapy中使用任意你熟悉的網(wǎng)頁數(shù)據(jù)提取工具,但是,scrapy本身也為我們提供了一套提取數(shù)據(jù)的機制,我們稱之為選擇器(seletors),他們通過特定的 XPath 或者 CSS 表達式來“選擇” HTML文件中的某個部分。XPath 是一門用來在XML文件中選擇節(jié)點的語言,也可以用在HTML上。 CSS 是一門將HTML文檔樣式化的語言。選擇器由它定義,并與特定的HTML元素的樣式相關(guān)連。
Scrapy選擇器構(gòu)建于 lxml 庫之上,這意味著它們在速度和解析準確性上非常相似。下面我們來了解scrapy選擇器。

使用選擇器

scrapy中調(diào)用選擇器的方法非常的簡單,下面我們從實例中進行學(xué)習(xí)。
我們還是以博客園首頁的信息作為例子,演示使用選擇器抓取數(shù)據(jù),下圖是首頁的html信息,我們下面就是抓取標(biāo)題,鏈接,閱讀數(shù),評論數(shù)。

import scrapy
from scrapy.selector import Selector

class Cnblog_Spider(scrapy.Spider):

    name = "cnblog"
    allowed_domains = ["cnblogs.com"]
    start_urls = [
     'https://www.cnblogs.com/',
    ]

    def parse(self, response):
        selector = Selector(response=response)
        title = selector.xpath('//a[@class="titlelnk"]/text()').extract()
        link = selector.xpath('//a[@class="titlelnk"]/@href').extract()
        read = selector.xpath('//span[@class="article_comment"]/a/text()').extract()
        comment = selector.xpath('//span[@class="article_view"]/a/text()').extract()
        print('這是title:',title)
        print('這是鏈接:', link)
        print('這是閱讀數(shù)', read)
        print('這是評論數(shù)', comment)

選擇器的使用可以分為下面的三步:

  1. 導(dǎo)入選擇器from scrapy.selector import Selector
  2. 創(chuàng)建選擇器實例selector = Selector(response=response)
  3. 使用選擇器selector.xpath()或者selector.css()

當(dāng)然你可以使用xpath或者css中的任意一種或者組合使用,怎么方便怎么來,至于xpath和css語法,你可以去額外學(xué)習(xí),仔細觀察,你會發(fā)現(xiàn)每個選擇器最后都有一個extract(),你可以嘗試去掉這個看一下,區(qū)別在于,當(dāng)你沒有使用extract()的時候,提取出來的內(nèi)容依然具有選擇器屬性,簡而言之,你可以繼續(xù)使用里面的內(nèi)容進行提取下級內(nèi)容,而當(dāng)你使用了extract()之后,提取出來的內(nèi)容就會變成字符串格式了。我們進行多級提取的時候,這會很有用。值得注意的是,選擇器提取出來的內(nèi)容是放在列表里面的,即使沒有內(nèi)容,那也是一個空列表,下面我們運行這個爬蟲,你會發(fā)現(xiàn)內(nèi)容已經(jīng)被提取出來了。

事實上,我們可以完全不用那么麻煩,因為scrapy為我們提供了選擇器的簡易用法,當(dāng)我們需要選擇器的時候,只要一步就可以了,如下:

import scrapy

class Cnblog_Spider(scrapy.Spider):
    name = "cnblog"
    allowed_domains = ["cnblogs.com"]
    start_urls = [
        'https://www.cnblogs.com/',
    ]

    def parse(self, response):
        title = response.xpath('//a[@class="titlelnk"]/text()').extract()
        link = response.xpath('//a[@class="titlelnk"]/@href').extract()
        read = response.xpath('//span[@class="article_comment"]/a/text()').extract()
        comment = response.xpath('//span[@class="article_view"]/a/text()').extract()
        print('這是title:', title)
        print('這是鏈接:', link)
        print('這是閱讀數(shù)', read)
        print('這是評論數(shù)', comment)

可以看到,我們直接使用response.xpath()就可以了,并沒有導(dǎo)入什么,實例化什么,可以說非常方便了,當(dāng)然直接response.css()一樣可以。

拓展

scrapy為我們提供的選擇器還有一些其他的特點,這里我們簡單的列舉

  • extract()
    >>> response.xpath('//title/text()')
    [<Selector (text) xpath=//title/text()>]
    >>> response.css('title::text')
    [<Selector (text) xpath=//title/text()>]
    
    前面已經(jīng)提到了,.xpath() 及 .css() 方法返回一個類 SelectorList 的實例, 它是一個新選擇器的列表,就是說,你依然可以使用里面的元素進行向下提取,因為它還是一個選擇器,為了提取真實的原文數(shù)據(jù),我們需要調(diào)用 .extract()
  • extract_first()
    如果想要提取到第一個匹配到的元素, 可以調(diào)用response.xpath('//span[@class="article_view"]/a/text()').extract_first() 這樣我們就拿到了第一個匹配的數(shù)據(jù),當(dāng)然,我們之前提到了選擇器返回的數(shù)據(jù)是一個列表,那么你當(dāng)然可以使用response.xpath('//span[@class="article_view"]/a/text()').extract()[0]拿到第一個匹配的數(shù)據(jù),這和response.xpath('//span[@class="article_view"]/a/text()')[0].extract()效果是一樣的,值得注意的是,如果是空列表,這兩種方法的區(qū)別就出現(xiàn)了,extract_first()會返回None,而后面的那種方法,就會因列表為空而報錯。
    除此之外,我們還可以為extract_first()設(shè)置默認值,當(dāng)空列表時,就會返回一個我們設(shè)置的值,比如:extract_first(default='not-found')

結(jié)合正則表達式

你會發(fā)現(xiàn),之前我們匹配的閱讀數(shù),評論數(shù)都會有漢字在里面,如果我們只想提取里面的數(shù)字呢,這個時候就可以使用正則表達式和選擇器配合來實現(xiàn),比如下面:

import scrapy

class Cnblog_Spider(scrapy.Spider):
    name = "cnblog"
    allowed_domains = ["cnblogs.com"]
    start_urls = [
        'https://www.cnblogs.com/',
    ]

    def parse(self, response):
        read = response.xpath(
                '//span[@class="article_comment"]/a/text()').re('\d+')
        comment = response.xpath(
                '//span[@class="article_view"]/a/text()').re('\d+')
        print('這是閱讀數(shù)', read)
        print('這是評論數(shù)', comment)

運行一下,可以看到,效果就出來了。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • scrapy學(xué)習(xí)筆記(有示例版) 我的博客 scrapy學(xué)習(xí)筆記1.使用scrapy1.1創(chuàng)建工程1.2創(chuàng)建爬蟲模...
    陳思煜閱讀 12,760評論 4 46
  • Python版本管理:pyenv和pyenv-virtualenvScrapy爬蟲入門教程一 安裝和基本使用Scr...
    inke閱讀 15,511評論 6 12
  • scrapy是python最有名的爬蟲框架之一,可以很方便的進行web抓取,并且提供了很強的定制型,這里記錄簡單學(xué)...
    bomo閱讀 2,160評論 1 11
  • 姓名:童濤 學(xué)號:16020150020 嵌牛導(dǎo)讀:共享經(jīng)濟的熱潮讓諸多產(chǎn)業(yè)都開始蹭“共享”的熱點,比如共享籃球、...
    童小濤閱讀 275評論 0 0
  • 戰(zhàn)爭的硝煙,在,慢慢的散去 可八十多年前一幕,依舊,歷歷在目 那是一個國度的危難 那關(guān)系到一個民族的,生死存亡 你...
    麒帆閱讀 317評論 0 13