beautifulsoup
Elementos de localización
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()