Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BeautifulSoup exclude content within a certain tag(s)

I have the following item to find the text in a paragraph:

soup.find("td", { "id" : "overview-top" }).find("p", { "itemprop" : "description" }).text

How would I exclude all text within an <a> tag? Something like in <p> but not in <a>?

like image 767
David542 Avatar asked Dec 22 '14 20:12

David542


2 Answers

Find and join all text nodes in the p tag and check that it's parent is not an a tag:

p = soup.find("td", {"id": "overview-top"}).find("p", {"itemprop": "description"})

print ''.join(text for text in p.find_all(text=True) 
              if text.parent.name != "a")

Demo (see no link text printed):

>>> from bs4 import BeautifulSoup
>>> 
>>> data = """
... <td id="overview-top">
...     <p itemprop="description">
...         text1
...         <a href="google.com">link text</a>
...         text2
...     </p>
... </td>
... """
>>> soup = BeautifulSoup(data)
>>> p = soup.find("td", {"id": "overview-top"}).find("p", {"itemprop": "description"})
>>> print p.text

        text1
        link text
        text2
>>>
>>> print ''.join(text for text in p.find_all(text=True) if text.parent.name != "a")

        text1

        text2
like image 121
alecxe Avatar answered Sep 20 '22 12:09

alecxe


Using lxml,

import lxml.html as LH

data = """
<td id="overview-top">
    <p itemprop="description">
        text1
        <a href="google.com">link text</a>
        text2
    </p>
</td>
"""

root = LH.fromstring(data)
print(''.join(root.xpath(
    '//td[@id="overview-top"]//p[@itemprop="description"]/text()')))

yields

        text1

        text2

To also get the text of child tags of <p>, just use a double forward slash, //text(), instead of a single forward slash:

print(''.join(root.xpath(
    '//td[@id="overview-top"]//p[@itemprop="description"]//text()')))

yields

        text1
        link text
        text2
like image 37
unutbu Avatar answered Sep 21 '22 12:09

unutbu