How to extract text between tags containing unwanted BR tags with xpath and python?

Tags: ,



Within a div tag there is text I wan to extract but within a leading introduction and a footer which is unfortunatelly inside the div.

There are always 3 BR tags at the beginning and 2 BR tags at the end of the text, where the text inbetween might also be devided with BR tags itself.

The simple example looks like this:

   <div class="text" itemprop="description">
            bla
        <br>
            bla
        <br>
        <br>
            text
        <br>
            text
        <br>
            text
        <br>
        <br>
            bla
    </div>

The full example:

response.xpath(‘//div[@itemprop=”description”]’).extract_first()

'<div class="text" itemprop="description">jung<br><br>Wunderschöner, sanfter Pyrenäenberghund Rüde schweren Herzens abzugeben. Rudi ist Anfang Juli letzten Jahres bei uns geboren und hat sich mittlerweile zu einem stattlichen jungen Mann entwickelt. Er ist ein total freundliches Kerlchen im Umgang mit seinen Mitmenschen, egal ob groß oder klein, und versteht sich auch mit Katzen und anderen Tieren wie auch z.B. Ziegen. Es kristallisierte sich auch schnell heraus, dass er der intelligenteste unserer 11 Welpen war. Sitz und Platz klappte innerhalb kürzester Zeit, da er sehr lernwillig ist. Er hat bis März bei uns gelebt und war dann für 1,5 Monate in einer anderen Familie, wo es aber leider Probleme innerhalb des Rudels gab und die neuen Besitzer ihn daher wieder zu uns gegeben haben. Es war aber nicht seine Schuld, dass es nicht funktioniert hat, er hat sich nicht falsch verhalten. Wir wünschen uns für ihn, dass er einen Platz findet, wo man die Eigenschaften eines Herdenschutzhundes zu schätzen und lieben weiß. Deshalb ist es uns sehr wichtig, dass die neuen Besitzer bereits Erfahrung mit Herdenschutzhunden haben. Außerdem wäre es schön, wenn er einen Partner zum Spielen hätte, da er es als Einzelhund nicht kennt. Rudi ist selbstverständlich gechippt, geimpft und entwurmt.<br><br>Weitere Angaben: Rüde, EU-Heimtierausweis, entwurmt, gechipt, geimpft, nur für Hundeerfahrene, verträglich mit Katzen, Familienhund, kinderfreundlich.</div>'

Trying to remove the tags by performing a string method did not solve the issue, as I will also remove the BR inbetween and I do also want to remove the unwanted header/footer.

response.xpath('string(//div[@itemprop="description"])').extract_first()

Expected output:

Wunderschöner, sanfter Pyrenäenberghund Rüde schweren Herzens abzugeben. Rudi ist Anfang Juli letzten Jahres bei uns geboren und hat sich mittlerweile zu einem stattlichen jungen Mann entwickelt. Er ist ein total freundliches Kerlchen im Umgang mit seinen Mitmenschen, egal ob groß oder klein, und versteht sich auch mit Katzen und anderen Tieren wie auch z.B. Ziegen. Es kristallisierte sich auch schnell heraus, dass er der intelligenteste unserer 11 Welpen war. Sitz und Platz klappte innerhalb kürzester Zeit, da er sehr lernwillig ist. Er hat bis März bei uns gelebt und war dann für 1,5 Monate in einer anderen Familie, wo es aber leider Probleme innerhalb des Rudels gab und die neuen Besitzer ihn daher wieder zu uns gegeben haben. Es war aber nicht seine Schuld, dass es nicht funktioniert hat, er hat sich nicht falsch verhalten. Wir wünschen uns für ihn, dass er einen Platz findet, wo man die Eigenschaften eines Herdenschutzhundes zu schätzen und lieben weiß. Deshalb ist es uns sehr wichtig, dass die neuen Besitzer bereits Erfahrung mit Herdenschutzhunden haben. Außerdem wäre es schön, wenn er einen Partner zum Spielen hätte, da er es als Einzelhund nicht kennt. Rudi ist selbstverständlich gechippt, geimpft und entwurmt.

Expected removal:

jung



Weitere Angaben: Rüde, EU-Heimtierausweis, entwurmt, gechipt, geimpft, nur für Hundeerfahrene, verträglich mit Katzen, Familienhund, kinderfreundlich.

How can the leading text and the footer text be removed and the rest extracted?

Answer

You can use the following XPath :

//div[@itemprop="description"]/text()[not(position()=last())][preceding-sibling::*[2][self::br]][normalize-space()]

Code :

data = """HTML
<div class="text" itemprop="description">jung<br><br>Wunderschöner, sanfter Pyrenäenberghund Rüde schweren Herzens abzugeben. Rudi ist Anfang Juli letzten Jahres bei uns geboren und hat sich mittlerweile zu einem stattlichen jungen Mann entwickelt. Er ist ein total freundliches Kerlchen im Umgang mit seinen Mitmenschen, egal ob groß oder klein, und versteht sich auch mit Katzen und anderen Tieren wie auch z.B. Ziegen. Es kristallisierte sich auch schnell heraus, dass er der intelligenteste unserer 11 Welpen war. Sitz und Platz klappte innerhalb kürzester Zeit, da er sehr lernwillig ist. Er hat bis März bei uns gelebt und war dann für 1,5 Monate in einer anderen Familie, wo es aber leider Probleme innerhalb des Rudels gab und die neuen Besitzer ihn daher wieder zu uns gegeben haben. Es war aber nicht seine Schuld, dass es nicht funktioniert hat, er hat sich nicht falsch verhalten. Wir wünschen uns für ihn, dass er einen Platz findet, wo man die Eigenschaften eines Herdenschutzhundes zu schätzen und lieben weiß. Deshalb ist es uns sehr wichtig, dass die neuen Besitzer bereits Erfahrung mit Herdenschutzhunden haben. Außerdem wäre es schön, wenn er einen Partner zum Spielen hätte, da er es als Einzelhund nicht kennt. Rudi ist selbstverständlich gechippt, geimpft und entwurmt.<br><br>Weitere Angaben: Rüde, EU-Heimtierausweis, entwurmt, gechipt, geimpft, nur für Hundeerfahrene, verträglich mit Katzen, Familienhund, kinderfreundlich.</div>
HTML"""

import lxml.html
tree = lxml.html.fromstring(data)
print (tree.xpath('//div[@itemprop="description"]/text()[not(position()=last())][preceding-sibling::*[2][self::br]][normalize-space()]'))

Output :

['Wunderschöner, sanfter Pyrenäenberghund Rüde schweren Herzens abzugeben. Rudi ist Anfang Juli letzten Jahres bei uns geboren und hat sich mittlerweile zu einem stattlichen jungen Mann entwickelt. Er ist ein total freundliches Kerlchen im Umgang mit seinen Mitmenschen, egal ob groß oder klein, und versteht sich auch mit Katzen und anderen Tieren wie auch z.B. Ziegen. Es kristallisierte sich auch schnell heraus, dass er der intelligenteste unserer 11 Welpen war. Sitz und Platz klappte innerhalb kürzester Zeit, da er sehr lernwillig ist. Er hat bis März bei uns gelebt und war dann für 1,5 Monate in einer anderen Familie, wo es aber leider Probleme innerhalb des Rudels gab und die neuen Besitzer ihn daher wieder zu uns gegeben haben. Es war aber nicht seine Schuld, dass es nicht funktioniert hat, er hat sich nicht falsch verhalten. Wir wünschen uns für ihn, dass er einen Platz findet, wo man die Eigenschaften eines Herdenschutzhundes zu schätzen und lieben weiß. Deshalb ist es uns sehr wichtig, dass die neuen Besitzer bereits Erfahrung mit Herdenschutzhunden haben. Außerdem wäre es schön, wenn er einen Partner zum Spielen hätte, da er es als Einzelhund nicht kennt. Rudi ist selbstverständlich gechippt, geimpft und entwurmt.']

Tested OK with :

EDIT : XPath explanation :

We look for text nodes child of a specific div. The text nodes has to fulfill the following conditions :

  • not to be the last text node (to exclude “Weitere Angaben…”)
  • the second preceding sibling element of the text node has to be a br element (to exclude the first text elements like dog breed and statut)

That way, the XPath expression select the text nodes after the first two consecutive br (<br/><br/>) and stop before the last text node.



Source: stackoverflow