1. 程式人生 > >scrapy:選擇器selector

scrapy:選擇器selector

當抓取網頁時,常見的任務是從HTML原始碼中提取資料。現有的一些庫可以達到這個目的:

  • BeautifulSoup
  • lxml

Scrapy 提取資料有自己的一套機制。它們被稱作選擇器(seletors),因為他們通過特定的 XPath 或者 CSS 表示式來“選擇” HTML 檔案中的某個部分。

構造選擇器

Scrapy selector 是以 文字(Text)或 TextResponse 構造的 Selector。其根據輸入型別自動選擇最優的分析方法(XML vs HTML):

>>> from scrapy.selector import Selector
>>> from
scrapy.http import HtmlResponse

以文字構造:

>>> body = '<html><body><span>good</span></body></html>'
>>> Selector(text=body).xpath('//span/text()').extract()
[u'good']

以 response 構造:

>>> response = HtmlResponse(url='http://example.com', body=body)
>>> Selector(response=response).xpath('
//span/text()').extract() [u'good']

為了方便起見,response 物件以 .selector 屬性提供了一個 selector:

>>> response.selector.xpath('//span/text()').extract()
[u'good']

使用選擇器

 使用 Scrapy Shell 和 Scrapy 文件伺服器的一個樣例頁面,來解釋如何使用選擇器:

複製程式碼
<html>
 <head>
  <base href='http://example.com/' />
  <title>Example website</
title> </head> <body> <div id='images'> <a href='image1.html'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a> <a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a> <a href='image3.html'>Name: My image 3 <br /><img src='image3_thumb.jpg' /></a> <a href='image4.html'>Name: My image 4 <br /><img src='image4_thumb.jpg' /></a> <a href='image5.html'>Name: My image 5 <br /><img src='image5_thumb.jpg' /></a> </div> </body> </html>
複製程式碼

首先開啟 Shell:

scrapy shell http://doc.scrapy.org/en/latest/_static/selectors-sample1.html

當 shell 載入後,將獲得名為 response 的 shell 變數,其為響應的 response,並且在其 response.selector 屬性上綁定了一個 selector。

因為處理的是 HTML,選擇器自動使用 HTML 語法分析。

那麼,通過檢視 HTML code 該頁面的原始碼,可以構建一個 XPath 來選擇 title 標籤內的文字:

>>> response.selector.xpath('//title/text()')
[<Selector (text) xpath=//title/text()>]

由於在 response 中使用 XPath、CSS 查詢十分普遍,因此,Scrapy 提供了兩個實用的快捷方式:

response.xpath()

response.css()

>>> response.xpath('//title/text()')
[<Selector (text) xpath=//title/text()>]
>>> response.css('title::text')
[<Selector (text) xpath=//title/text()>]

.xpath() 以及 .css() 方法返回一個類 SelectList 的例項,它是一個新選擇器的列表。這個 API 可以用來快速的提取巢狀資料。

為了提取真實的原文資料,需要呼叫 .extract() 方法如下:

>>> response.xpath('//title/text()').extract()
[u'Example website']

CSS 選擇器可以使用 CSS3 偽元素(pseudo-elements)來選擇文字或者屬性節點:

>>> response.css('title::text').extract()
[u'Example website']

獲取得到根 URL(base URL)和一些圖片連結:

複製程式碼
>>> response.xpath('//base/@href').extract()
[u'http://example.com/']

>>> response.css('base::attr(href)').extract()
[u'http://example.com/']

>>> response.xpath('//a[contains(@href, "image")]/@href').extract()
[u'image1.html',
 u'image2.html',
 u'image3.html',
 u'image4.html',
 u'image5.html']

>>> response.css('a[href*=image]::attr(href)').extract()
[u'image1.html',
 u'image2.html',
 u'image3.html',
 u'image4.html',
 u'image5.html']

>>> response.xpath('//a[contains(@href, "image")]/img/@src').extract()
[u'image1_thumb.jpg',
 u'image2_thumb.jpg',
 u'image3_thumb.jpg',
 u'image4_thumb.jpg',
 u'image5_thumb.jpg']

>>> response.css('a[href*=image] img::attr(src)').extract()
[u'image1_thumb.jpg',
 u'image2_thumb.jpg',
 u'image3_thumb.jpg',
 u'image4_thumb.jpg',
 u'image5_thumb.jpg']
複製程式碼

巢狀選擇器

選擇器方法(.xpath() or css())返回相同型別的選擇器列表,因此也可以對這些選擇器呼叫選擇器方法:

複製程式碼
>>> links = response.xpath('//a[contains(@href, "image")]')
>>> links.extract()
[u'<a href="image1.html">Name: My image 1 <br><img src="image1_thumb.jpg"></a>',
 u'<a href="image2.html">Name: My image 2 <br><img src="image2_thumb.jpg"></a>',
 u'<a href="image3.html">Name: My image 3 <br><img src="image3_thumb.jpg"></a>',
 u'<a href="image4.html">Name: My image 4 <br><img src="image4_thumb.jpg"></a>',
 u'<a href="image5.html">Name: My image 5 <br><img src="image5_thumb.jpg"></a>']

>>> for index, link in enumerate(links):
        args = (index, link.xpath('@href').extract(), link.xpath('img/@src').extract())
        print 'Link number %d points to url %s and image %s' % args

Link number 0 points to url [u'image1.html'] and image [u'image1_thumb.jpg']
Link number 1 points to url [u'image2.html'] and image [u'image2_thumb.jpg']
Link number 2 points to url [u'image3.html'] and image [u'image3_thumb.jpg']
Link number 3 points to url [u'image4.html'] and image [u'image4_thumb.jpg']
Link number 4 points to url [u'image5.html'] and image [u'image5_thumb.jpg']
複製程式碼

結合正則表示式使用選擇器

Selector 也有一個 .re() 方法,用來通過正則表示式來提取資料。然而,不同於使用 .xpath() 或者 .css() 方法,.re() 方法返回 Unicode 字串的列表。所以無法構造巢狀式的 .re() 呼叫。

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

使用相對 XPaths

如果使用巢狀的選擇器,並且使用起始為 / 的 XPath, 那麼該 XPath 將對文件使用絕對路徑,而且對於你呼叫的 Selector 不是相對路徑。

比如,假設要提取 <div> 元素中所有的 <p> 元素。首先,先得到所有的 <div> 元素:

>>> divs = response.xpath('//div')

開始時,你也許會嘗試使用下面的錯誤的方法,因為它其實是從整篇文件中,而不是僅僅從那些 <div> 元素內部提取所有的 <p> 元素:

>>> for p in divs.xpath('//p'):  # this is wrong - gets all <p> from the whole document
...     print p.extract()

下面是比較適合的處理方法(注意 .//p XPath的點字首):

>>> for p in divs.xpath('.//p'):  # extracts all <p> inside
...     print p.extract()

另一種常見的情況是提取所有直系的 <p> 元素:

>>> for p in divs.xpath('p'):
...     print p.extract()

使用 EXSLT 擴充套件

因建於 lxml 之上,Scrapy 選擇器也支援一些 EXSLT 擴充套件,可以在 XPath 表示式中使用這些預先指定的名稱空間:

字首名稱空間用途
rehttp://exslt.org/regular-expressions正則表示式
sethttp://exslt.org/sets集合操作

正則表示式

例如在 XPath 的 starts-with() 或 contains() 無法滿足需求時,test() 函式可以非常有用。

例如在列表中選擇有 “class” 元素且結尾為一個數字的連結:

複製程式碼
>>> from scrapy import Selector
>>> doc = """
... <div>
...     <ul>
...         <li class="item-0"><a href="link1.html">first item</a></li>
...         <li class="item-1"><a href="link2.html">second item</a></li>
...         <li class="item-inactive"><a href="link3.html">third item</a></li>
...         <li class="item-1"><a href="link4.html">fourth item</a></li>
...         <li class="item-0"><a href="link5.html">fifth item</a></li>
...     </ul>
... </div>
... """
>>> sel = Selector(text=doc, type="html")
>>> sel.xpath('//li//@href').extract()
[u'link1.html', u'link2.html', u'link3.html', u'link4.html', u'link5.html']
>>> sel.xpath('//li[re:test(@class, "item-\d$")]//@href').extract()
[u'link1.html', u'link2.html', u'link4.html', u'link5.html']
>>>
複製程式碼

警告:C 語言庫 libxslt 不支援 EXSLT 正則表示式,因此 lxml 在實現時使用了 Python re 模組的鉤子。因此,在 XPath 表示式中使用 regexp 函式可能會犧牲少量的效能。

集合操作

集合操作可以方便地用於在提取文字元素前從文件樹種去除一些部分。

例如使用 itemscopes 組合對應的 itemprops 來提取微資料(來自 http://schema.org/Product 的樣本內容)

複製程式碼
>>> doc = """
... <div itemscope itemtype="http://schema.org/Product">
...   <span itemprop="name">Kenmore White 17" Microwave</span>
...   <img src="kenmore-microwave-17in.jpg" alt='Kenmore 17" Microwave' />
...   <div itemprop="aggregateRating"
...     itemscope itemtype="http://schema.org/AggregateRating">
...    Rated <span itemprop="ratingValue">3.5</span>/5
...    based on <span itemprop="reviewCount">11</span> customer reviews
...   </div>
...
...   <div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
...     <span itemprop="price">$55.00</span>
...     <link itemprop="availability" href="http://schema.org/InStock" />In stock
...   </div>
...
...   Product description:
...   <span itemprop="description">0.7 cubic feet countertop microwave.
...   Has six preset cooking categories and convenience features like
...   Add-A-Minute and Child Lock.</span>
...
...   Customer reviews:
...
...   <div itemprop="review" itemscope itemtype="http://schema.org/Review">
...     <span itemprop="name">Not a happy camper</span> -
...     by <span itemprop="author">Ellie</span>,
...     <meta itemprop="datePublished" content="2011-04-01">April 1, 2011
...     <div itemprop="reviewRating" itemscope itemtype="http://schema.org/Rating">
...       <meta itemprop="worstRating" content = "1">
...       <span itemprop="ratingValue">1</span>/
...       <span itemprop="bestRating">5</span>stars
...     </div>
...     <span itemprop="description">The lamp burned out and now I have to replace
...     it. </span>
...   </div>
...
...   <div itemprop="review" itemscope itemtype="http://schema.org/Review">
...     <span itemprop="name">Value purchase</span> -
...     by <span itemprop="author">Lucas</span>,
...     <meta itemprop="datePublished" content="2011-03-25">March 25, 2011
...     <div itemprop="reviewRating" itemscope itemtype="http://schema.org/Rating">
...       <meta itemprop="worstRating" content = "1"/>
...       <span itemprop="ratingValue">4</span>/
...       <span itemprop="bestRating">5</span>stars
...     </div>
...     <span itemprop="description">Great microwave for the price. It is small and
...     fits in my apartment.</span>
...   </div>
...   ...
... </div>
... """
>>>
>>> for scope in sel.xpath('//div[@itemscope]'):
...     print "current scope:", scope.xpath('@itemtype').extract()
...     props = scope.xpath('''
...                 set:difference(./descendant::*/@itemprop,
...                                .//*[@itemscope]/*/@itemprop)''')
...     print "    properties:", props.extract()
...     print
...

current scope: [u'http://schema.org/Product']
    properties: [u'name', u'aggregateRating', u'offers', u'description', u'review', u'review']

current scope: [u'http://schema.org/AggregateRating']
    properties: [u'ratingValue', u'reviewCount']

current scope: [u'http://schema.org/Offer']
    properties: [u'price', u'availability']

current scope: [u'http://schema.org/Review']
    properties: [u'name', u'author', u'datePublished', u'reviewRating', u'description']

current scope: [u'http://schema.org/Rating']
    properties: [u'worstRating', u'ratingValue', u'bestRating']

current scope: [u'http://schema.org/Review']
    properties: [u'name', u'author', u'datePublished', u'reviewRating', u'description']

current scope: [u'http://schema.org/Rating']
    properties: [u'worstRating', u'ratingValue', u'bestRating']

>>>
複製程式碼

在這裡,首先在 itemscope 元素上迭代,對於其中的每一個元素,我們尋找所有的 itemprops 元素,並排除那些身在另一個 itemscope 內的元素。

內建選擇器的參考

class scrapy.selector.Selector(response=None, text=None, type=None)

Selector 的例項時對選擇某些內容響應的封裝。

response 是 HTMLResponse 或 XMLResponse 的一個物件,將被用來選擇和提取資料。

text 是在 response 不可用時的一個 unicode 字串或 utf-8 編碼的文字。將 text 和 response 一起使用時未定義行為。

type 定義了選擇器型別,可以是 html, xml 或 None(預設)。

如果 type 是 None,選擇器會根據 response 型別(參見下面)自動選擇最佳型別,或者在和 text 一起使用時,預設為 html。

如果 type 是None,並傳遞了一個 response,選擇器型別將從 response 型別中推導如下:

  • "html" for HtmlResponse type
  • "xml" for XmlResponse type
  • "html" for anything else

其他情況下,如果設定了 type ,選擇器型別將被強制設定,而不進行檢測。

xpath(query)

尋找可以匹配 xpath query 的節點,並返回一個 SelectorList 的一個例項結果,單一化其所有元素。列表元素也實現了 Selector 的介面。

query 是包含 XPath 查詢請求的字串。

方便起見該方法也可以通過 response.xpath() 呼叫。

css(query)

css(query)

應用給定的 CSS 選擇器,返回 SelectorList 的一個例項。

相關推薦

scrapy:選擇selector

當抓取網頁時,常見的任務是從HTML原始碼中提取資料。現有的一些庫可以達到這個目的:BeautifulSouplxmlScrapy 提取資料有自己的一套機制。它們被稱作選擇器(seletors),因為他們通過特定的 XPath 或者 CSS 表示式來“選擇” HTML 檔案中

NIO 選擇 Selector

字節 () 激發 就是 異常檢查 執行 1.4 移植 異常   選擇器提供選擇執行已經就緒的任務的能力,這使得多元 I/O 成為可能。就像在第一章中描述的那樣,就緒選擇和多元執行使得單線程能夠有效率地同時管理多個 I/O 通道(Channels)。C/C++代碼的工具箱中,

Java Nio選擇Selector

Selector(選擇器)是Java NIO中能夠檢測一到多個NIO通道,並能夠知曉通道是否為諸如讀寫事件做好準備的元件。這樣,一個單獨的執行緒可以管理多個channel,從而管理多個網路連線 ,減少伺服器的效能開銷。 建立Selector 通過Selector 提供的

JAVA jsoup 爬蟲 傻瓜入門實錄 (2-1) 選擇 Selector 實務分解說明

JAVA jsoup 爬蟲 傻瓜入門實錄 (2-1) 選擇器 Selector 實務分解說明這部分要講解的是個人常用的jsoup選擇器說明上一篇我們講完各種型態解析成Document型態的方法實做當我們解析成Document後 就可以開始做爬蟲的動作爬蟲前我們應該先分析要抓取的網頁資料你要抓的資料是在哪個di

css中選擇(selector)

常用選擇器 最常用的選擇器型別時型別選擇器和後代選擇器。型別選擇器用來尋找特定型別的元素,比如段落或標題元素,只需指定希望特定型別的元素,比如段落或標題元素,只需要指定希望應用樣式的額元素的名稱。來興選擇器有時候也稱為元素選擇器或者簡單選擇器。 p{co

Scrapy選擇的用法

當我們抓取網頁時,最常見任務就是從HTML原始碼中提取資料,可是怎麼提取資料呢?當然就是用選擇器了。本節課主要介紹CSS,Xpath,正則表示式,pyquery四種選擇器。四大選擇器Scrapy 提取資料有自己的一套機制。它們被稱作選擇器(seletors),通過特定的 Xp

深入淺出JMS(四)--ActiveMQ訊息選擇Selector

一、序言        訊息大多數情況都是傳送到broker 的,在知道Destination 的情況下,都可以消費,因此有些情況下需要我們將訊息分組、隔離,或則指定A訊息,只能有A消費者消費等等情況,這裡做個大概的介紹和例項。 二、例項場景        我們通過有時候

Java NIO 選擇(Selector)的內部實現(poll epoll)

之前強調這麼多關於linux核心的poll及epoll,無非是想讓大家先有個認識: Java NIO中的選擇器依賴作業系統核心的這些系統呼叫,我們這裡只講解與linux核心相關的NIO實現,當然,windows或其他作業系統實現大體上是類似的,相信大家也可以觸類旁通。 那

CheckBox使用選擇Selector

第一步,layout檔案中設定checkbox屬性: android:button="@null"//這樣設定能解決checkbox在選中下不會顯示系統預設打勾圖示,否則設定選擇器會重疊自定義圖示 第二步,在drawable包下新建selecor檔案,準備兩張圖片,一張選中

JS API-新的選擇 selector

新的選擇器 document.querySelector("selector"); selector:根據CSS選擇器返回第一個匹配到的元素,如果沒有匹配到,則返回null; 支援: Chrome 4.0+, FireFox 3.5+, Safari 3.2+, Oper

android中listview的item點選切換實現效果(選擇selector

public class V2_Adapter_TarentoCreateActivity_OverSea_City extends BaseAdapter{private V2_TarentoCreateActivity_OverSea_Place v2_TarentoCreateActivity_Over

scrapy選擇歸納

http ont jpg 擁有 div tex tar pytho 們的 python 爬蟲: srcrapy框架xpath和css選擇器語法 Xpath基本語法 一、常用的路徑表達式: 表達式描述實例 nodename 選取nodename節點的所有子節點 //

Java NIO通俗程式設計之選擇Selector(四)

最後一步就是根據不同的事件,編寫相應的處理程式碼:/* * 根據不同的事件做處理 * */ protected void process(SelectionKey key) throws IOException{ // 接收請求 if (key.isAcceptable()) {

NIO中和選擇Selector

NIO中和選擇器Selector 在上一篇的JAVA中NIO再深入我們學會了如何使用Buffer,而在Java中IO和NIO中我們

Java NIO 選擇 Selector

選擇器 Selector 是 I/O 多路複用的核心元件,它可以監控實現了 SelectableChannel 的[通道](https://www.cnblogs.com/robothy/p/14234437.html)的就緒情況。有了多路複用(multiplexing) I/O 模型,使得單執行緒的 Jav

單獨使用 Scrapy 框架的 Selector 選擇

mywang88 2018-12-16 背景 Scrapy 框架是一個經典的 Python 爬蟲框架。 Scrapy 框架中的 Selector 類提供了多種 html/xml 節點選擇器的方法,例如:css 選擇器、xpath 選擇器、re 選擇器等。 使用 scrap

小白學 Python 爬蟲(35):爬蟲框架 Scrapy 入門基礎(三) Selector 選擇

人生苦短,我用 Python 前文傳送門: 小白學 Python 爬蟲(1):開篇 小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝 小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門 小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門 小白學 Pyth

Scrapy』終端調用&選擇方法

selector 我們 resp 必須 數據結構 tor ipy lec 結合 Scrapy終端 示例,輸入如下命令後shell會進入Python(或IPython)交互式界面: scrapy shell "http://www.itcast.cn/channel/t

scrapy xpath選擇多級選擇錯誤

span resp rap spa rac res pat style 出現 在學習scrapy中用xpath提取網頁內容時,有時要先提取出一整個行標簽內容,再從行標簽裏尋找目標內容。出現一個錯誤。 錯誤代碼: def parse(self, response):

3-4:has(selector)過濾選擇

除了在上一小節介紹的使用包含的字串內容過濾元素之外,還可以使用包含的元素名稱來過濾,:has(selector)過濾選擇器的功能是獲取選擇器中包含指定元素名稱的全部元素,其中selector引數就是包含的元素名稱,是被包含元素。 例如:獲取指定包含某個元素名的全部<li>元素,並