Scrapy之Selector詳解

1、簡介

前面介紹了scrapy命令Scrapy處理流程與重要組件 css

這裏介紹一下Scrapy的Selector,Scrapy的Selector和Beautifulsoup很是像,關於Beautifulsoup能夠參考BeautifuSoup實用方法屬性總結 BeautifulSoup詳解html

先來看一下Selector的知識點: Selector知識點正則表達式

2、xpath

咱們先介紹一下xpath,由於xpath語法比較簡潔,而且若是可以靈活應用的話,能夠簡化咱們提取HTML內容的複雜度。scrapy

符號 說明
/ 從根節點選取,使用絕對路徑,路徑必須徹底匹配
// 從整個文檔中選取,使用相對路徑
. 從當前節點開始選取
.. 從當前節點父節點開始選取
@ 選取屬性

光看說明有些抽象,咱們經過一個例子來簡單說明一下:.net

# -*- coding:utf-8 -*-
from scrapy import Selector

content = '''
<div>
    <p>out inner div p</p>
    <div id="inner"><p>in inner div p</p></div>
</div>
<p>out div p</p>
'''

selector = Selector(text=content)

# 在整個文檔中選取id爲inner的div節點
inner_div_sel = selector.xpath("//div[@id='inner']")
# 獲取整個文檔中的p節點的文本
print(inner_div_sel.xpath('//p/text()').getall())
# 從inner div節點的父節點開始獲取全部p節點的文本
print(inner_div_sel.xpath('..//p/text()').getall())
# 從inner div節點開始獲取全部p節點的文本
print(inner_div_sel.xpath('.//p/text()').getall())

Scrapy的Selector和BeautifulSoup同樣,能夠經過字符串來構造相應的對象,而後就可使用xpath相關的語法來解析HTML。code

inner_div_sel = selector.xpath("//div[@id='inner']")

首先@在xpath中表示選取屬性,@id就表示選取id屬性,//div[@id='inner']就表示,選取id屬性值爲inner的div標籤。htm

inner_div_sel.xpath('//p/text()').getall()

上面的語句的輸出是:對象

['out inner div p', 'in inner div p', 'out div p']

很奇怪,咱們已經在inner的div節點選取p,爲何獲取到了全部的p?blog

由於在xpath中,//表示從整個文檔中選取,只要相對路徑匹配就能夠ip

全部選取了文檔中的全部p節點。

.和..就很是容易理解了,就是當前路徑,和當前路徑的上一級路徑,路徑必須徹底匹配。

3、獲取值

# -*- coding:utf-8 -*-

from scrapy import Selector

content = '''
<html>
 <head>
  <title>selector css</title>
 </head>
 <body>
    <ul>
        <li>ul 1 li 1</li>
        <li>ul 1 li 2</li>
    </ul>
    <ul>
        <li>ul 2 li 1</li>
        <li>ul 2 li 2</li>
    </ul>
 </body>
</html>
'''

selector = Selector(text=content)

# get獲取第一個
print(selector.css('li::text').get())
print(selector.css('li::text').extract_first())

# getall獲取列表
print(selector.css('li::text').getall())
print(selector.css('li::text').c())

# ['<li>ul 1 li 1</li>', '<li>ul 2 li 1</li>']
print(selector.xpath('//li[1]').getall())
# ['<li>ul 1 li 1</li>']
print(selector.xpath('(//li)[1]').getall())

# 沒找到返回None
print(selector.xpath('//div[@id="ne"]/text()').get())
# 給定默認值
print(selector.xpath('//div[@id="ne"]/text()').get(default='default-value'))

獲取值使用get,getall,extract_first,extract方法,其中get與extract_first是獲取第一個元素,getall和extract方法是獲取全部元素,返回的是一個列表。

4、css選擇

# -*- coding:utf-8 -*-

from scrapy import Selector

content = '''
<html>
 <head>
  <title>attribute</title>
 </head>
 <body>
  <div id='images'>
   <a href='image1.html'>a text 1<img src='img1.png' /></a>
   <a href='image2.html'>a text 2<img src='img2.png' /></a>
   <a href='image3.html'>a text 3<img src='img3.png'>img3 text</img></a>
   <a href='image4.html'>a text 4<img /></a>
   <a href='http://mycollege.vip'>a text 5<img src='img5.jpg' /></a>
  </div>
 </body>
</html>
'''

selector = Selector(text=content)

# 獲取第一個img標籤的src屬性
print(selector.css('img').attrib['src'])

# 獲取全部a標籤的href屬性
print(selector.css('a::attr(href)').getall())
# 選擇有href屬性而且href屬性中包含image的a標籤
print(selector.css('a[href*=image]::attr(href)').getall())
# 選擇href屬性包含image的a標籤下的屬性包含src的標籤
print(selector.css('a[href*=image] img::attr(src)').getall())

# 獲取img的文本
print(selector.css('img::text').getall())
print(selector.css('img::text').get(default='default-value'))

# 獲取id爲imgages節點下的全部文本
print(selector.css('#images *::text').getall())
print(selector.css('title::text').get())

# xpath獲取屬性
print(selector.xpath('//a/@href').getall())
print(selector.xpath('//img/@src').getall())

Scrapy的css就是實現了css選擇器,而且作了必定的擴展,能夠更加方便的獲取咱們最經常使用的文本和屬性。

5、xpath擴展

# -*- coding:utf-8 -*-

"""
test()
starts-with()
contains()
"""

from scrapy import Selector


content = '''
<html>
 <head>
  <title>selector css</title>
 </head>
 <body>
    <ul>
        <li class="nav1"><a href="http://www.mycollege.vip"></a>nav1 text</li>
        <li class="nav2"><a href="http://www.mycollege.vip"></a>nav2 text</li>
        <li class="nav33"><a href="http://www.mycollege.vip"></a>nav33 text</li>
        <li class="clz1"><a href="http://www.mycollege.vip/xx.png"></a></li>
        <li class="clz1 clz2"><a href="https://www.mycollege.vip"></a></li>
    </ul>
 </body>
</html>
'''

selector = Selector(text=content, type="html")

# 選擇class值匹配正則表達式nav\d$的li
print(selector.xpath(r'//li[re:test(@class, "nav\d$")]//text()').getall())

# 選擇類包含clz1的li
print(selector.xpath('//li[has-class("clz1")]').getall())
# 選擇類既包含clz1又包含clz2的li
print(selector.xpath('//li[has-class("clz1", "clz2")]').getall())
# 選擇屬性href包含png的a標籤
print(selector.xpath('//a[contains(@href, "png")]/@href').getall())
# 選取href屬性以https開頭的a標籤
print(selector.xpath('//a[starts-with(@href, "https")]/@href').getall())

對於xpath的擴展主要有判斷是否包含指定類的has-class方法,屬性是否包含指定字符串的contains方法,屬性是否以指定字符串開頭的starts-with方法。

相關文章
相關標籤/搜索