Sopa Linda - Procurando na árvore
Existem muitos métodos Beautifulsoup, que nos permitem pesquisar uma árvore de análise. Os dois métodos mais comuns e usados são find () e find_all ().
Antes de falar sobre find () e find_all (), vamos ver alguns exemplos de diferentes filtros que você pode passar para esses métodos.
Tipos de Filtros
Temos diferentes filtros que podemos passar para esses métodos e a compreensão desses filtros é crucial, pois esses filtros são usados repetidamente em toda a API de pesquisa. Podemos usar esses filtros com base no nome da tag, em seus atributos, no texto de uma string ou em uma combinação deles.
Uma linha
Um dos tipos mais simples de filtro é uma string. Passar uma string para o método de busca e Beautifulsoup realizará uma correspondência com aquela string exata.
O código abaixo encontrará todas as tags <p> no 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>]
Expressão regular
Você pode encontrar todas as tags começando com uma determinada string / tag. Antes disso, precisamos importar o módulo re para usar a expressão regular.
>>> 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
Você pode passar várias tags para localizar, fornecendo uma lista. O código abaixo encontra todas as tags <b> e <pre> -
>>> markup.find_all(['pre', 'b'])
[<pre>Programming Languages are:</pre>, <b>Java, Python, Cplusplus</b>]
Verdadeiro
True retornará todas as tags que puder encontrar, mas nenhuma string por conta própria -
>>> 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 retornar apenas as marcas da sopa acima -
>>> for tag in markup.find_all(True):
(tag.name)
'html'
'body'
'p'
'p'
'pre'
'p'
'b'
encontrar tudo()
Você pode usar find_all para extrair todas as ocorrências de uma tag específica da resposta da página como -
Sintaxe
find_all(name, attrs, recursive, string, limit, **kwargs)
Vamos extrair alguns dados interessantes do IMDB - “Filmes com melhor classificação” de todos os tempos.
>>> 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
Acima, podemos ver que find_all nos dará todos os itens que correspondem aos critérios de pesquisa que definimos. Todos os filtros que podemos usar com find_all () podem ser usados com find () e outros métodos de pesquisa também como find_parents () ou find_siblings ().
encontrar()
Como vimos acima, find_all () é usado para escanear todo o documento para encontrar todo o conteúdo, mas algo, o requisito é encontrar apenas um resultado. Se você sabe que o documento contém apenas uma tag <body>, é perda de tempo pesquisar o documento inteiro. Uma maneira é chamar find_all () com limit = 1 toda vez ou então podemos usar o método find () para fazer o mesmo -
Sintaxe
find(name, attrs, recursive, string, **kwargs)
Portanto, a seguir, dois métodos diferentes fornecem a mesma saída -
>>> soup.find_all('title',limit=1)
[<title>IMDb Top 250 - IMDb</title>]
>>>
>>> soup.find('title')
<title>IMDb Top 250 - IMDb</title>
Nas saídas acima, podemos ver que o método find_all () retorna uma lista contendo um único item, enquanto o método find () retorna um único resultado.
Outra diferença entre os métodos find () e find_all () é -
>>> soup.find_all('h2')
[]
>>>
>>> soup.find('h2')
Se o método soup.find_all () não puder encontrar nada, ele retornará uma lista vazia enquanto find () retornará Nenhum.
find_parents () e find_parent ()
Ao contrário dos métodos find_all () e find () que percorrem a árvore, observando os descendentes da tag, os métodos find_parents () e find_parents () fazem o oposto, eles percorrem a árvore para cima e olham para os pais de uma tag (ou string).
Sintaxe
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/MV5BM2MyNjYxNmUtYTAwNi00MTYxLWJmNWYtYzZlODY3ZTk3OTFlXkEyXkFqcGdeQXVyNzkwMjQ5NzM@._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>]
Existem oito outros métodos semelhantes -
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)
Onde,
find_next_siblings() e find_next_sibling() os métodos irão iterar sobre todos os irmãos do elemento que vêm depois do atual.
find_previous_siblings() e find_previous_sibling() métodos irão iterar sobre todos os irmãos que vêm antes do elemento atual.
find_all_next() e find_next() os métodos irão iterar sobre todas as tags e strings que vêm após o elemento atual.
find_all_previous e find_previous() métodos irão iterar sobre todas as tags e strings que vêm antes do elemento atual.
Seletores CSS
A biblioteca BeautifulSoup para suportar os seletores CSS mais comumente usados. Você pode pesquisar elementos usando seletores CSS com a ajuda do método select ().
Aqui estão alguns exemplos -
>>> 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>]