Scrapy進階知識點總結(二)——選擇器Selectors


1. Selectors選擇器

在抓取網頁時,您需要執行的最常見任務是從HTML源提取數據。有幾個庫可用於實現此目的,例如:

  • BeautifulSoup是Python程序員中非常流行的Web抓取庫,它基於HTML代碼的結構構造Python對象,並且相當好地處理壞標記,但它有一個缺點:它很慢。
  • lxml是一個XML解析庫(也可以解析HTML),它使用基於ElementTree的pythonic API 。(lxml不是Python標准庫的一部分。)

Scrapy帶有自己的提取數據機制。它們被稱為選擇器,因為它們“選擇”由XPath或CSS表達式指定的HTML文檔的某些部分。

XPath是一種用於在XML文檔中選擇節點的語言,也可以與HTML一起使用。CSS是一種將樣式應用於HTML文檔的語言。它定義選擇器以將這些樣式與特定HTML元素相關聯。

Selector是基於lxml來構建的,支持XPath選擇器、CSS選擇器以及正則表達式,功能全面,解析速度和准確度非常高。

 

2. 選擇器使用

1.通過response響應對象屬性.selector構建選擇器實例

response.selector.xpath('//span/text()').get()

使用XPath和CSS查詢響應非常常見,響應包括另外兩個快捷方式:response.xpath()和response.css():

>>> response.xpath('//span/text()').get()
'good'
>>> response.css('span::text').get()
'good'

 

2.直接使用Selectors構建

從HTML文本構造

>>> from scrapy.selector import Selector
>>> body = '<html><body><span>good</span></body></html>'
>>> Selector(text=body).xpath('//span/text()').get()
'good'

從響應構造

>>> from scrapy.selector import Selector
>>> from scrapy.http import HtmlResponse
>>> response = HtmlResponse(url='http://example.com', body=body)
>>> Selector(response=response).xpath('//span/text()').get()
'good'

 

3. CSS選擇器

基礎選擇器

選擇器 含義
* 通用元素選擇器,匹配頁面任何元素(這也就決定了我們很少使用)
#id id選擇器,匹配特定id的元素
.class 類選擇器,匹配class包含(不是等於)特定類的元素
element 標簽選擇器 根據標簽選擇元素
[attr] 屬性選擇器 根據元素屬性去選擇

組合選擇器

選擇器 示例 示例說明 含義
elementE,elementF div,p 選擇所有<div>元素和<p>元素 多元素選擇器,用”,分隔,同時匹配元素E或元素F
elementE elementF div p 選擇<div>元素內的所有<p>元素 后代選擇器,用空格分隔,匹配E元素所有的后代(不只是子元素、子元素向下遞歸)元素F
elementE>elementF div>p 選擇所有父級是 <div> 元素的 <p> 元素 子元素選擇器,用”>”分隔,匹配E元素的所有直接子元素
elementE+elementF div+p 選擇所有緊接着<div>元素之后的<p>元素 直接相鄰選擇器,匹配E元素之后相鄰同級元素F
elementE~elementF p~ul 選擇p元素之后的每一個ul元素 普通相鄰選擇器,匹配E元素之后同級元素F(無論直接相鄰與否)
.class1.class2 .user.login 匹配如<div class="user login">元素 匹配類名中既包含class1又包含class2的元素

CSS選擇器是前端的基礎,以上只給了比較重要的內容,具體CSS選擇器內容可以去w3school參考

 

Scrapy中CSS選擇器的拓展

根據W3C標准,CSS選擇器不支持選擇文本節點或屬性值。但是在Web抓取環境中選擇這些是非常重要的,Scrapy(parsel)實現了一些非標准的偽元素

  • 要選擇文本節點,使用 ::text
  • 選擇屬性值,用::attr(name) name是指你想要的價值屬性的名稱
#沒有用::text,對selectors對象使用get方法后,返回的是匹配的html元素

>>> response.css('title').get()
<title>Example website</title>

#使用::text就是返回標簽內的文本

>>> response.css('title::text').get()
'Example website'

#<a href='image1.html'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a> 使用a::attr(href)可以提取屬性

>>>response.css('a::attr(href)').get()
'image1.html'

 

4. XPath

XPath,全稱 XML Path Language,即 XML 路徑語言,它是一門在XML文檔中查找信息的語言。XPath 最初設計是用來搜尋XML文檔的,但是它同樣適用於 HTML 文檔的搜索。

1.XPath 使用路徑表達式在 XML 文檔中選取節點。節點是通過沿着路徑或者 step 來選取的。 下面列出了最有用的路徑表達式

表達式 描述
nodename 選取此節點的所有子節點。
/ 從根節點選取。
// 從匹配選擇的當前節點選擇文檔中的節點,而不考慮它們的位置。
. 選取當前節點。
.. 選取當前節點的父節點。
@ 選取屬性。

舉例如下

路徑表達式 結果
bookstore 選取 bookstore 元素的所有子節點。
/bookstore

選取根元素 bookstore。

注釋:假如路徑起始於正斜杠( / ),則此路徑始終代表到某元素的絕對路徑!

bookstore/book 選取屬於 bookstore 的子元素的所有 book 元素。
//book 選取所有 book 子元素,而不管它們在文檔中的位置。
bookstore//book 選擇屬於 bookstore 元素的后代的所有 book 元素,而不管它們位於 bookstore 之下的什么位置。
//@lang 選取名為 lang 的所有屬性。

2.謂語用來查找某個特定的節點或者包含某個指定的值的節點。謂語被嵌在方括號中。

路徑表達式 結果
/bookstore/book[1] 選取屬於 bookstore 子元素的第一個 book 元素。
/bookstore/book[last()] 選取屬於 bookstore 子元素的最后一個 book 元素。
/bookstore/book[last()-1] 選取屬於 bookstore 子元素的倒數第二個 book 元素。
/bookstore/book[position()<3] 選取最前面的兩個屬於 bookstore 元素的子元素的 book 元素。
//title[@lang] 選取所有擁有名為 lang 的屬性的 title 元素。
//title[@lang='eng'] 選取所有 title 元素,且這些元素擁有值為 eng 的 lang 屬性。
/bookstore/book[price>35.00] 選取 bookstore 元素的所有 book 元素,且其中的 price 元素的值須大於 35.00。
/bookstore/book[price>35.00]/title 選取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值須大於 35.00。

3.選取未知節點

通配符 描述
* 匹配任何元素節點。
@* 匹配任何屬性節點。
node() 匹配任何類型的節點。

實例如下:

路徑表達式 結果
/bookstore/* 選取 bookstore 元素的所有子元素。
//* 選取文檔中的所有元素。
//title[@*] 選取所有帶有屬性的 title 元素。

同樣scrapy也給XPath拓展了方法,使用.//text()可以選擇文本

摘自https://www.w3school.com.cn/xpath/xpath_syntax.asp

 

5. .xpath()和.css()方法

css(query)

應用給定的CSS選擇器並返回一個SelectorList實例。(SelectorList實例可以理解為Selector組成的list)

query 是一個包含要應用的CSS選擇器的字符串。

在后台,CSS查詢使用cssselect庫和run .xpath()方法轉換為XPath查詢 。

>>> response.css("link")
[<Selector xpath='descendant-or-self::link' data='<link rel="alternate" type="text/html" h'>,
 <Selector xpath='descendant-or-self::link' data='<link rel="next" type="application/atom+'>,
 ...

 

xpath(query, namespaces=None, **kwargs)

查找與xpath匹配的節點query,並將結果作為SelectorList實例返回, 並將所有元素展平。List元素也實現了Selector接口。

query 是一個包含要應用的XPATH查詢的字符串。

namespaces是一個可選的映射(dict),用於注冊的人的附加前綴。相反,這些前綴不會保存以供將來調用。

>>> response.xpath("//link")
[<Selector xpath='//link' data='<link rel="alternate" type="text/html" h'>,
 <Selector xpath='//link' data='<link rel="next" type="application/atom+'>,
 ...

 

串聯查詢

由於css()與xpath()方法返回SelectorList實例,並且SelectorList實例也有與Selector對象相同的方法(SelectorList實例的方法可以理解為list中所有Selector遍歷執行),所以可以在返回結果上繼續查詢

response.css(".quote").css("small")

#這個就是先查找出所有class=quote的元素,然后在這些元素中查找small標簽元素

 

6. .get()與.getall()

get()

unicode字符串返回第一個真實的數據,沒有css xpath拓展方法(::text ::attr //text()),就返回匹配的html元素數據

getall()

以unicode字符串list返回所有數據,其它同get()一樣

默認返回值

如果沒有匹配到元素則返回None,但是可以提供默認返回值作為參數,以代替None

>>> response.xpath('//div[@id="not-exists"]/text()').get(default='not-found')
'not-found'

.get() .getall()與extract() extract_first()

SelectorList.get()與SelectorList.extract_first()實際是一樣的,同理SelectorList.getall()與SelectorList.extract()相同

 

7. Selector其他屬性方法

.attrib

返回底層元素的屬性字典

 

>>> response.css('img').attrib['src']
'image1_thumb.jpg'

re(regex,replace_entities = True )

Selector還有一種.re()使用正則表達式提取數據的方法。但是,與 .xpath()或 .css()不同,.re()返回unicode字符串列表。所以你不能構造嵌套的.re()調用。

>>> response.xpath('//a[contains(@href, "image")]/text()').re(r'Name:\s*(.*)')
['My image 1',
 'My image 2',
 'My image 3',
 'My image 4',
 'My image 5']

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM