Buscar..


Localiza un texto después de un elemento en BeautifulSoup.

Imagina que tienes el siguiente HTML:

<div>
    <label>Name:</label>
    John Smith
</div>

Y necesitas ubicar el texto "John Smith" después del elemento de label .

En este caso, puede ubicar el elemento de label por texto y luego usar la propiedad .next_sibling :

from bs4 import BeautifulSoup

data = """
<div>
    <label>Name:</label>
    John Smith
</div>
"""

soup = BeautifulSoup(data, "html.parser")

label = soup.find("label", text="Name:")
print(label.next_sibling.strip())

Imprime John Smith .

Usando selectores de CSS para ubicar elementos en BeautifulSoup

BeautifulSoup tiene un soporte limitado para los selectores de CSS , pero cubre los más utilizados. Use el método select() para encontrar múltiples elementos y select_one() para encontrar un solo elemento.

Ejemplo básico:

from bs4 import BeautifulSoup

data = """
<ul>
    <li class="item">item1</li>
    <li class="item">item2</li>
    <li class="item">item3</li>
</ul>
"""

soup = BeautifulSoup(data, "html.parser")

for item in soup.select("li.item"):
    print(item.get_text())

Huellas dactilares:

item1
item2
item3

Ubicando comentarios

Para ubicar los comentarios en BeautifulSoup , use el argumento de text (o string en las versiones recientes) que verifique el tipo de Comment :

from bs4 import BeautifulSoup
from bs4 import Comment

data = """
<html>
    <body>
        <div>
        <!-- desired text -->
        </div>
    </body>
</html>
"""

soup = BeautifulSoup(data, "html.parser")
comment = soup.find(text=lambda text: isinstance(text, Comment))
print(comment)

Imprime el desired text .

Funciones de filtro

BeautifulSoup le permite filtrar resultados al proporcionar una función para find_all y todas funciones similares. Esto puede ser útil para filtros complejos, así como una herramienta para la reutilización de código.

Uso básico

Defina una función que tome un elemento como único argumento. La función debería devolver True si el argumento coincide.

def has_href(tag):
    '''Returns True for tags with a href attribute'''
    return  bool(tag.get("href"))

soup.find_all(has_href) #find all elements with a href attribute
#equivilent using lambda:
soup.find_all(lambda tag: bool(tag.get("href")))

Otro ejemplo que encuentra etiquetas con un valor href que no comienza con

Proporcionar argumentos adicionales para filtrar funciones

Dado que la función pasada a find_all solo puede tomar un argumento, a veces es útil hacer que las "fábricas de funciones" que producen funciones se ajusten para su uso en find_all . Esto es útil para hacer que las funciones de búsqueda de etiquetas sean más flexibles.

def present_in_href(check_string):
    return lambda tag: tag.get("href") and check_string in tag.get("href")

soup.find_all(present_in_href("/partial/path"))

Acceso a etiquetas internas y sus atributos de etiqueta inicialmente seleccionada

Supongamos que tienes un html después de seleccionar con soup.find('div', class_='base class') :

from bs4 import BeautifulSoup

soup = BeautifulSoup(SomePage, 'lxml')
html = soup.find('div', class_='base class')
print(html)

<div class="base class">
  <div>Sample text 1</div>
  <div>Sample text 2</div>
  <div>
    <a class="ordinary link" href="https://example.com">URL text</a>
  </div>
</div>

<div class="Confusing class"></div>
'''

Y si desea acceder a href la etiqueta <a> , puede hacerlo de esta manera:

a_tag = html.a
link = a_tag['href']
print(link)

https://example.com

Esto es útil cuando no puede seleccionar directamente la etiqueta <a> porque los attrs no le dan una identificación única, hay otras etiquetas "gemelas" <a> en la página analizada. Pero puede seleccionar de forma única una etiqueta principal que contenga la <a> necesaria.

Recopilación de elementos opcionales y / o sus atributos de series de páginas.

Consideremos una situación cuando analiza el número de páginas y desea recopilar el valor del elemento que es opcional (puede presentarse en una página y puede estar ausente en otra) para una página específica.

Además, el elemento en sí mismo, por ejemplo, es el elemento más común en la página, en otras palabras, ningún atributo específico puede ubicarlo de manera única. Pero ve que puede seleccionar correctamente su elemento principal y sabe el número de orden del elemento deseado en el nivel de anidamiento respectivo.

from bs4 import BeautifulSoup

soup = BeautifulSoup(SomePage, 'lxml')
html = soup.find('div', class_='base class') # Below it refers to html_1 and html_2

El elemento deseado es opcional, por lo que podría haber 2 situaciones para que html sea:

html_1 = '''
<div class="base class">    # №0
  <div>Sample text 1</div>  # №1
  <div>Sample text 2</div>  # №2  
  <div>!Needed text!</div>  # №3
</div>

<div>Confusing div text</div>  # №4
'''
        
html_2 = '''
<div class="base class">    # №0
  <div>Sample text 1</div>  # №1
  <div>Sample text 2</div>  # №2  
</div>

<div>Confusing div text</div>  # №4
'''

¡Si tienes html_1 puedes recopilar !Needed text! de la etiqueta №3 de esta manera:

wanted tag = html_1.div.find_next_sibling().find_next_sibling() # this gives you whole tag №3

Inicialmente obtiene div1 div , luego 2 veces cambia al siguiente div en el mismo nivel de anidamiento para llegar a №3.

wanted_text = wanted_tag.text # extracting !Needed text!

La utilidad de este enfoque viene cuando se obtiene html_2 : el enfoque no le dará un error, le dará None :

print(html_2.div.find_next_sibling().find_next_sibling())
None

El uso de find_next_sibling() aquí es crucial porque limita la búsqueda de elementos por nivel de anidamiento respectivo. Si utilizarías find_next() , la etiqueta №4 se recopilará y no la querrás:

print(html_2.div.find_next().find_next())
<div>Confusing div text</div>

También puede explorar find_previous_sibling() y find_previous() que funcionan de manera opuesta.

Todas las funciones descritas tienen sus múltiples variantes para capturar todas las etiquetas, no solo la primera:

find_next_siblings()
find_previous_siblings()
find_all_next()
find_all_previous()


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow