Beautiful Soup - Buscando en el árbol
Hay muchos métodos de Beautifulsoup, que nos permiten buscar en un árbol de análisis. Los dos métodos más comunes y usados son find () y find_all ().
Antes de hablar sobre find () y find_all (), veamos algunos ejemplos de diferentes filtros que puede pasar a estos métodos.
Tipos de filtros
Tenemos diferentes filtros que podemos pasar a estos métodos y la comprensión de estos filtros es crucial, ya que estos filtros se utilizan una y otra vez en toda la API de búsqueda. Podemos usar estos filtros basados en el nombre de la etiqueta, en sus atributos, en el texto de una cadena o una combinación de estos.
Una cuerda
Uno de los tipos de filtro más simples es una cadena. Pasando una cadena al método de búsqueda y Beautifulsoup realizará una coincidencia con esa cadena exacta.
A continuación, el código encontrará todas las etiquetas <p> en el documento:
>>> markup = BeautifulSoup('<p>Top Three</p><p><pre>Programming Languages are:</pre></p><p><b>Java, Python, Cplusplus</b></p>')
>>> markup.find_all('p')
[<p>Top Three</p>, <p></p>, <p><b>Java, Python, Cplusplus</b></p>]
Expresión regular
Puede encontrar todas las etiquetas que comienzan con una cadena / etiqueta determinada. Antes de eso, necesitamos importar el módulo re para usar expresiones regulares.
>>> import re
>>> markup = BeautifulSoup('<p>Top Three</p><p><pre>Programming Languages are:</pre></p><p><b>Java, Python, Cplusplus</b></p>')
>>>
>>> markup.find_all(re.compile('^p'))
[<p>Top Three</p>, <p></p>, <pre>Programming Languages are:</pre>, <p><b>Java, Python, Cplusplus</b></p>]
Lista
Puede pasar varias etiquetas para buscar proporcionando una lista. Debajo del código se encuentran todas las etiquetas <b> y <pre> -
>>> markup.find_all(['pre', 'b'])
[<pre>Programming Languages are:</pre>, <b>Java, Python, Cplusplus</b>]
Cierto
True devolverá todas las etiquetas que pueda encontrar, pero no las cadenas por sí mismas.
>>> markup.find_all(True)
[<html><body><p>Top Three</p><p></p><pre>Programming Languages are:</pre>
<p><b>Java, Python, Cplusplus</b> </p> </body></html>,
<body><p>Top Three</p><p></p><pre> Programming Languages are:</pre><p><b>Java, Python, Cplusplus</b></p>
</body>,
<p>Top Three</p>, <p></p>, <pre>Programming Languages are:</pre>, <p><b>Java, Python, Cplusplus</b></p>, <b>Java, Python, Cplusplus</b>]
Para devolver solo las etiquetas de la sopa anterior:
>>> for tag in markup.find_all(True):
(tag.name)
'html'
'body'
'p'
'p'
'pre'
'p'
'b'
encuentra todos()
Puede usar find_all para extraer todas las apariciones de una etiqueta en particular de la respuesta de la página como:
Sintaxis
find_all(name, attrs, recursive, string, limit, **kwargs)
Extraigamos algunos datos interesantes de IMDB- "Películas mejor calificadas" de todos los tiempos.
>>> url="https://www.imdb.com/chart/top/?ref_=nv_mv_250"
>>> content = requests.get(url)
>>> soup = BeautifulSoup(content.text, 'html.parser')
#Extract title Page
>>> print(soup.find('title'))
<title>IMDb Top 250 - IMDb</title>
#Extracting main heading
>>> for heading in soup.find_all('h1'):
print(heading.text)
Top Rated Movies
#Extracting sub-heading
>>> for heading in soup.find_all('h3'):
print(heading.text)
IMDb Charts
You Have Seen
IMDb Charts
Top India Charts
Top Rated Movies by Genre
Recently Viewed
Desde arriba, podemos ver que find_all nos dará todos los elementos que coinciden con los criterios de búsqueda que definimos. Todos los filtros que podemos usar con find_all () pueden usarse con find () y otros métodos de búsqueda también como find_parents () o find_siblings ().
encontrar()
Hemos visto anteriormente, find_all () se usa para escanear todo el documento para encontrar todo el contenido, pero algo, el requisito es encontrar solo un resultado. Si sabe que el documento contiene solo una etiqueta <body>, es una pérdida de tiempo buscar en todo el documento. Una forma es llamar a find_all () con limit = 1 cada vez o de lo contrario podemos usar el método find () para hacer lo mismo:
Sintaxis
find(name, attrs, recursive, string, **kwargs)
Entonces, a continuación, dos métodos diferentes dan el mismo resultado:
>>> soup.find_all('title',limit=1)
[<title>IMDb Top 250 - IMDb</title>]
>>>
>>> soup.find('title')
<title>IMDb Top 250 - IMDb</title>
En los resultados anteriores, podemos ver que el método find_all () devuelve una lista que contiene un solo elemento, mientras que el método find () devuelve un solo resultado.
Otra diferencia entre el método find () y find_all () es:
>>> soup.find_all('h2')
[]
>>>
>>> soup.find('h2')
Si el método soup.find_all () no puede encontrar nada, devuelve una lista vacía mientras que find () devuelve Ninguno.
find_parents () y find_parent ()
A diferencia de los métodos find_all () y find () que atraviesan el árbol, mirando los descendientes de la etiqueta, los métodos find_parents () y find_parents () hacen lo contrario, atraviesan el árbol hacia arriba y miran los padres de una etiqueta (o una cadena).
Sintaxis
find_parents(name, attrs, string, limit, **kwargs)
find_parent(name, attrs, string, **kwargs)
>>> a_string = soup.find(string="The Godfather")
>>> a_string
'The Godfather'
>>> a_string.find_parents('a')
[<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>]
>>> a_string.find_parent('a')
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
>>> a_string.find_parent('tr')
<tr>
<td class="posterColumn">
<span data-value="2" name="rk"></span>
<span data-value="9.149038526210072" name="ir"></span>
<span data-value="6.93792E10" name="us"></span>
<span data-value="1485540" name="nv"></span>
<span data-value="-1.850961473789928" name="ur"></span>
<a href="/title/tt0068646/"> <img alt="The Godfather" height="67" src="https://m.media-amazon.com/images/M/MV5BM2MyNjYxNmUt[email protected]._V1_UY67_CR1,0,45,67_AL_.jpg" width="45"/>
</a> </td>
<td class="titleColumn">
2.
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
<span class="secondaryInfo">(1972)</span>
</td>
<td class="ratingColumn imdbRating">
<strong title="9.1 based on 1,485,540 user ratings">9.1</strong>
</td>
<td class="ratingColumn">
<div class="seen-widget seen-widget-tt0068646 pending" data-titleid="tt0068646">
<div class="boundary">
<div class="popover">
<span class="delete"> </span><ol><li>1<li>2<li>3<li>4<li>5<li>6<li>7<li>8<li>9<li>10</li>0</li></li></li></li&td;</li></li></li></li></li></ol> </div>
</div>
<div class="inline">
<div class="pending"></div>
<div class="unseeable">NOT YET RELEASED</div>
<div class="unseen"> </div>
<div class="rating"></div>
<div class="seen">Seen</div>
</div>
</div>
</td>
<td class="watchlistColumn">
<div class="wlb_ribbon" data-recordmetrics="true" data-tconst="tt0068646"></div>
</td>
</tr>
>>>
>>> a_string.find_parents('td')
[<td class="titleColumn">
2.
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
<span class="secondaryInfo">(1972)</span>
</td>]
Hay otros ocho métodos similares:
find_next_siblings(name, attrs, string, limit, **kwargs)
find_next_sibling(name, attrs, string, **kwargs)
find_previous_siblings(name, attrs, string, limit, **kwargs)
find_previous_sibling(name, attrs, string, **kwargs)
find_all_next(name, attrs, string, limit, **kwargs)
find_next(name, attrs, string, **kwargs)
find_all_previous(name, attrs, string, limit, **kwargs)
find_previous(name, attrs, string, **kwargs)
Dónde,
find_next_siblings() y find_next_sibling() Los métodos iterarán sobre todos los hermanos del elemento que vienen después del actual.
find_previous_siblings() y find_previous_sibling() Los métodos iterarán sobre todos los hermanos que vienen antes del elemento actual.
find_all_next() y find_next() Los métodos iterarán sobre todas las etiquetas y cadenas que vienen después del elemento actual.
find_all_previous y find_previous() Los métodos iterarán sobre todas las etiquetas y cadenas que vienen antes del elemento actual.
Selectores de CSS
La biblioteca BeautifulSoup para admitir los selectores de CSS más utilizados. Puede buscar elementos usando selectores CSS con la ayuda del método select ().
A continuación se muestran algunos ejemplos:
>>> soup.select('title')
[<title>IMDb Top 250 - IMDb</title>, <title>IMDb Top Rated Movies</title>]
>>>
>>> soup.select("p:nth-of-type(1)")
[<p>The Top Rated Movie list only includes theatrical features.</p>, <p> class="imdb-footer__copyright _2-iNNCFskmr4l2OFN2DRsf">© 1990-2019 by IMDb.com, Inc.</p>]
>>> len(soup.select("p:nth-of-type(1)"))
2
>>> len(soup.select("a"))
609
>>> len(soup.select("p"))
2
>>> soup.select("html head title")
[<title>IMDb Top 250 - IMDb</title>, <title>IMDb Top Rated Movies</title>]
>>> soup.select("head > title")
[<title>IMDb Top 250 - IMDb</title>]
#print HTML code of the tenth li elemnet
>>> soup.select("li:nth-of-type(10)")
[<li class="subnav_item_main">
<a href="/search/title?genres=film_noir&sort=user_rating,desc&title_type=feature&num_votes=25000,">Film-Noir
</a> </li>]