Quiero analizar una página html usando beautifulsoup. Quiero extraer texto dentro de una etiqueta sin eliminar las etiquetas html internas. por ejemplo entrada de muestra:

<a class="fl" href="https://stackoverflow.com/questio...">
    Angular2 <b>Router link not working</b>
</a>

Salida de muestra:

'Angular2 <b>Router link not working</b>'

He probado esto:

from bs4 import Beautifulsoup
string = '<a class="fl" href="https://stackoverflow.com/questio...">
         Angular2 <b>Router link not working</b>
         </a>'
soup = Beautifulsoup(string, 'html.parser')
print(soup.text)

Pero da:

'Angular2 Router link not working'

¿Cómo puedo extraer texto sin eliminar las etiquetas internas?

1
hamid 11 oct. 2019 a las 11:19

3 respuestas

La mejor respuesta

Desde aquí la primera respuesta funciona bien. Para este ejemplo:

from bs4 import Beautifulsoup
string = '<a class="fl" href="https://stackoverflow.com/questio...">
             Angular2 <b>Router link not working</b>
         </a>'
soup = BeautifulSoup(string, 'html.parser')
soup.find('a').encode_contents().decode('utf-8')

Da:

'Angular2 <b>Router link not working</b>'
2
hamid 11 oct. 2019 a las 09:33

Sí, como lo indicó Den, deberá tomar esa etiqueta interna y luego almacenarla como tipo str para incluir esa etiqueta interna. En la solución dada por Den, eso capturará exclusivamente las etiquetas <b>, no la etiqueta / texto principal y no si hay otro tipo de etiquetas de estilo dentro. Pero si hay otras etiquetas, puede ser más general y hacer que encuentre los elementos secundarios de la etiqueta <a>, en lugar de encontrar la etiqueta <b> específicamente.

Entonces, esencialmente, lo que esto hará es encontrar la etiqueta <a> y tomar todo el texto. Luego irá dentro de los elementos secundarios de esa etiqueta <a>, la convertirá en una cadena, luego reemplazará el texto de ese texto principal, con la cadena (que incluye las etiquetas)

string = '''<a class="fl" href="https://stackoverflow.com/questio...">
     Angular2 <b>Router link not working</b> and then this is in <i>italics</i> and this is in <b>bold</b>
     </a>'''



from bs4 import BeautifulSoup, Tag

soup = BeautifulSoup(string, 'html.parser')
parsed_soup = ''

for item in soup.find_all('a'):
    if type(item) is Tag and 'a' != item.name:
        continue
    else:
        try:
            parent = item.text.strip()
            child_elements = item.findChildren()
            for child_ele in child_elements:
                child_text = child_ele.text
                child_str = str(child_ele)


                parent = parent.replace(child_text, child_str)
        except:
            parent = item.text

print (parent)

Salida:

print (parent)
Angular2 <b>Router link not working</b> and then this is in <i>italics</i> and this is in <b>bold</b>
0
chitown88 11 oct. 2019 a las 09:29

Está extrayendo todo el texto de la etiqueta 'a', incluidas todas las etiquetas que contiene cuando escribe print(soup.text). Si desea obtener solo el objeto de etiqueta 'b', debe probar a continuación:

soup = BeautifulSoup(string, 'html.parser')
b = soup.find('b')
print(b)
print(type(b))

O

soup = BeautifulSoup(string, 'html.parser')
b = soup.find('a', class_="fl").find('b')
print(b)
print(type(b))

Salida:

<b>Router link not working</b>
<class 'bs4.element.Tag'>

Como puede ver, le devolverá su etiqueta 'b' en el objeto beautifullsoup

Si necesita datos en formato de cadena, simplemente puede escribir:

b = soup.find('a', class_="fl").find('b')
b = str(b)
print(b)
print(type(b))

Salida:

<b>Router link not working</b>
<class 'str'>
1
Den Lakusta 11 oct. 2019 a las 09:08
58337056