Home > scrapy, xpath > Xpath: funzioni

Xpath: funzioni

11 Ottobre 2017

Abbiamo parlato della parentele nella parte 1,
e delle abbreviazioni nella parte 2,
vediamo come utilizzare le funzioni messe a disposizione da Xpath.

Funzioni generiche

facciamo sempre riferimento al body:

<A-TAG class="a-class">A-text
    <B-TAG class="b-class">B-text</B-TAG>
    <B-TAG id="1">B-text
        <C-TAG class="c-class" id="3">C-text</C-TAG>
        <C-TAG class="c-class" id="4">C-text
            <D-TAG>D-text</D-TAG> 
        </C-TAG>
    </B-TAG>
    <B-TAG id="2">B-text
        <C-TAG id="5">C-text
            <D-TAG>D-text</D-TAG>
            <D-TAG id="6">D-text
                <E-TAG>E-text</E-TAG>
                <E-TAG>E-text
                    <F-TAG>F-text</F-TAG>
                </E-TAG>
            </D-TAG>
        </C-TAG>
    </B-TAG>
    <B-TAG attr="b-attr">B-text
        <C-TAG>C-text
            <D-TAG>D-text</D-TAG>
        </C-TAG>
    </B-TAG>
</A-TAG>

1. count()

Ritorna il numero dei nodi in un node-set:

>>> selector = Selector(text=body)
>>> selector.xpath('count(//b-tag)')
[<Selector xpath='count(//b-tag)' data=u'4.0'>]
>>> selector.xpath('count(//f-tag)')
[<Selector xpath='count(//f-tag)' data=u'1.0'>]

per comodità di lettura useremo il metodo extract_first() dell’ oggetto selector:

>>> selector.xpath('count(//b-tag)').extract_first()
u'4.0'
>>> selector.xpath('count(//f-tag)').extract_first()
u'1.0'

2. id()

Seleziona gli elementi in base al loro ID univoco:
id(’id_1’)

>>> selector.xpath('id(1)')
[<Selector xpath='id(1)' data=u'<b-tag id="1">B-text\n\n        <c-tag cla'>]

3. last()

Ritorna gli ultimi elementi di quel tipo:

>>> selector.xpath('//b-tag[last()]')
[<Selector xpath='//b-tag[last()]' data=u'<b-tag attr="b-attr">B-text\n\n        <c-'>]

Come si nota mancano i primi 3 b-tag.

>>> response.xpath('//foo[last()]')
[<Selector xpath='//foo[last()]' data=u'<foo>\n        <bar attr="z">z text</bar>'>]

4. name()

Ritorna il nome di un nodo:

>>> for n, s in enumerate(selector.xpath('//b-tag[name()]')): print n, s
... 
0 <Selector xpath='//b-tag[name()]' data=u'<b-tag class="b-class">B-text</b-tag>'>
1 <Selector xpath='//b-tag[name()]' data=u'<b-tag id="1">B-text\n\n        <c-tag cla'>
2 <Selector xpath='//b-tag[name()]' data=u'<b-tag id="2">B-text\n\n        <c-tag id='>
3 <Selector xpath='//b-tag[name()]' data=u'<b-tag attr="b-attr">B-text\n\n        <c-'>

5. position()

Ritorna la posizione nella lista nodi del nodo che viene processato:

>>> for pos in range(1, 5):
...     print pos, selector.xpath('//b-tag[position() = %s]' % pos)
... 
1 [<Selector xpath='//b-tag[position() = 1]' data=u'<b-tag class="b-class">B-text</b-tag>'>]
2 [<Selector xpath='//b-tag[position() = 2]' data=u'<b-tag id="1">B-text\n\n        <c-tag cla'>]
3 [<Selector xpath='//b-tag[position() = 3]' data=u'<b-tag id="2">B-text\n\n        <c-tag id='>]
4 [<Selector xpath='//b-tag[position() = 4]' data=u'<b-tag attr="b-attr">B-text\n\n        <c-'>]

6. contains()

Ritorna gli elementi per i quali la stringa passata come primo argomento, contiene la stringa
passata come secondo argomento

>>> for n, s in enumerate(selector.xpath('//*[contains(name(), "b-tag")]')): print n, s
... 
0 <Selector xpath='//*[contains(name(), "b-tag")]' data=u'<b-tag class="b-class">B-text</b-tag>'>
1 <Selector xpath='//*[contains(name(), "b-tag")]' data=u'<b-tag id="1">B-text\n\n        <c-tag cla'>
2 <Selector xpath='//*[contains(name(), "b-tag")]' data=u'<b-tag id="2">B-text\n\n        <c-tag id='>
3 <Selector xpath='//*[contains(name(), "b-tag")]' data=u'<b-tag attr="b-attr">B-text\n\n        <c-'>

In questo caso abbiamo filtrato tutti gli elementi i quali nomi (name()) contengono la stringa “b-tag”.
E’ possibile filtrare anche per attributo:

>>> for n, s in enumerate(selector.xpath('//b-tag[contains(@class, "b")]')): print n, s... 
0 <Selector xpath='//b-tag[contains(@class, "b")]' data=u'<b-tag class="b-class">B-text</b-tag>'>

7. starts-with()
Ritorna gli elementi per i quali la stringa passata come primo argomento, comincia con la stringa
passata come secondo argomento

>>> for n, s in enumerate(selector.xpath('//*[starts-with(name(), "f")]')): print n, s
... 
0 <Selector xpath='//*[starts-with(name(), "f")]' data=u'<f-tag>F-text</f-tag>'>

ci sono molte altre funzioni utilizzabili:

8. normalize-space()

Rimuove gli spazi ad inizio e fine stringa e sostituisce tutti gli spazi all’interno della stringa
con uno spazio solo:

>>> selector = scrapy.Selector(text='<bar name="bar1">  A text    spaced  </bar><bar name="bar2"> Another  text</bar>')
>>> selector.xpath('normalize-space(//bar)').extract()
[u'A text spaced']
>>> selector.xpath('normalize-space(//bar[@name="bar2"])').extract()
[u'Another text']

Funziona chiaramente anche sugli attributi:

>>> selector = scrapy.Selector(text='<bar name="  bar  1">  A text    spaced  </bar><bar name="bar2"> Another  text</bar>')
>>> selector.xpath('normalize-space(//bar/attribute::name)').extract()
[u'bar 1']

9. string()

Converte un argomento del nodo in oggetto, in stringa:

>>> selector = scrapy.Selector(text='<bar name="  bar  1">  A text    spaced  </bar><bar name="bar2"> Another  text</bar>')
>>> selector.xpath('string(//bar[1]/@name)').extract()
[u'  bar  1']

10. substring(string, start, n_chars)

Ritorna la parte di stringa specificata dal primo argomento (string),
partendo dall’indice indicato nel secondo argomento (start) e ritornando la
quantità di caratteri indicati dal terzo argomento (n_chars)

>>> selector = scrapy.Selector(text='<bar name="  bar  1">  A text    spaced  </bar><bar name="bar2"> Another  text</bar>')
>>> selector.xpath('//bar[1]/text()').extract_first()
u'  A text    spaced  '
>>> selector.xpath('substring(//bar[1]/text(), 5, 4)').extract_first()
u'text'

11. substring-after(string, prefix)

Ritorna la parte di stringa “string” che viene dopo la parte di stringa passata come
secondo argomento (prefix).

>>> selector = scrapy.Selector(text='<bar>string substring</bar>')
>>> selector.xpath('substring-after(//bar/text(), "string")').extract_first()
u' substring'

12. substring-before(string, siffix)

Ritorna la parte di stringa “string” che viene prima della parte di stringa passata come
secondo argomento (suffix).

>>> selector.xpath('substring-before(//bar/text(), "substring")').extract_first()
u'string '

13. translate(string, string_chars, new_chars)

Esegue una sostituzione carattere per carattere di una stringa (string), sostituendo i caratteri
della stringa stessa (string_chars) con quelli nuovi (new_chars):

>>> selector = scrapy.Selector(text='<bar>abcd</bar>')
>>> selector.xpath('translate(//bar/text(), "bc", "yz")').extract_first()
u'ayzd'

Funzioni numeriche

1. ceiling()

Ritorna il primo intero maggiore del numero dato:

>>> selector.xpath('ceiling(3.141)').extract_first()
u'4.0'

2. floor()

Ritorna il primo intero minore del numero dato:

>>> selector.xpath('floor(3.141)').extract_first()
u'3.0'

3. number()

Converte l’argomento passato in ingresso in numero quando possibile, o,
in caso contrario, in NAN:

>>> selector.xpath('number(100)').extract_first()
u'100.0'
>>> selector.xpath('number(a)').extract_first()
u'nan'

4. round()

Arrotonda il numero dato all’intero subito inferiore:

>>> selector.xpath('floor(1.999)').extract_first()
u'1.0'

5. sum()

Ritorna il totale da un insieme di numeri:

>>> selector = scrapy.Selector(text='<bar>1</bar><bar>2</bar>')
>>> selector.xpath('sum(//bar/text())').extract_first()
u'3.0'

6. not()
Ritorna gli elementi che non soddisfano un certo parametro:

>>> selector = scrapy.Selector(text='<bar name="bar1">1</bar><bar>2</bar>')
>>> selector.xpath('//bar[not(@name)]').extract()
[u'<bar>2</bar>']

In questo caso abbiamo selezionato gli elementi che NON hanno un attributo

Questo è quanto. Un buon punto di partenza per utilizzare xpath.

link utili:
parte 1. xpath: Appunti
parte 2. abbreviazioni
scrapy
xpath syntax

Categorie:scrapy, xpath Tag: ,
I commenti sono chiusi.