web-dev-qa-db-fra.com

Comment trouver des tags avec seulement certains attributs - BeautifulSoup

Comment utiliser BeautifulSoup pour rechercher des balises contenant SEULEMENT les attributs que je recherche?

Par exemple, je souhaite rechercher toutes les balises <td valign="top">.

Le code suivant: raw_card_data = soup.fetch('td', {'valign':re.compile('top')})

récupère toutes les données que je veux, mais saisit également toute balise <td> ayant l'attribut valign:top

J'ai aussi essayé: raw_card_data = soup.findAll(re.compile('<td valign="top">')) et cela ne retourne rien (probablement à cause d'une mauvaise expression régulière)

Je me demandais s'il y avait un moyen dans BeautifulSoup de dire "Trouver les balises <td> dont le seul attribut est valign:top"

UPDATEFOr exemple, si un document HTML contenait les balises <td> suivantes:

<td valign="top">.....</td><br />
<td width="580" valign="top">.......</td><br />
<td>.....</td><br />

Je voudrais que seule la première balise <td> (<td width="580" valign="top">) soit renvoyée

55
Snaxib

Comme expliqué sur la documentation BeutifulSoup

Vous pouvez utiliser ceci:

soup = BeautifulSoup(html)
results = soup.findAll("td", {"valign" : "top"})

MODIFIER :

Pour renvoyer des balises comportant uniquement l'attribut valign = "top", vous pouvez vérifier la longueur de la propriété tag attrs:

from BeautifulSoup import BeautifulSoup

html = '<td valign="top">.....</td>\
        <td width="580" valign="top">.......</td>\
        <td>.....</td>'

soup = BeautifulSoup(html)
results = soup.findAll("td", {"valign" : "top"})

for result in results :
    if len(result.attrs) == 1 :
        print result

Cela retourne:

<td valign="top">.....</td>
74
Loïc G.

Vous pouvez utiliser les fonctions lambda dans findAll comme expliqué dans documentation . Ainsi, dans votre cas, pour rechercher la balise td avec uniquement valign = "top", utilisez ce qui suit:

td_tag_list = soup.findAll(
                lambda tag:tag.name == "td" and
                len(tag.attrs) == 1 and
                tag["valign"] == "top")
32
Yogesh

si vous voulez rechercher uniquement avec un nom d'attribut avec une valeur

from bs4 import BeautifulSoup
import re

soup= BeautifulSoup(html.text,'lxml')
results = soup.findAll("td", {"valign" : re.compile(r".*")})

selon Steve Lorimer préférable de passer True au lieu de regex

results = soup.findAll("td", {"valign" : True})
13
Amr

Le moyen le plus simple de procéder consiste à utiliser la nouvelle méthode de style CSS select:

soup = BeautifulSoup(html)
results = soup.select('td[valign="top"]')
8
Chris Redford

Passez-le simplement comme argument de findAll:

>>> from BeautifulSoup import BeautifulSoup
>>> soup = BeautifulSoup("""
... <html>
... <head><title>My Title!</title></head>
... <body><table>
... <tr><td>First!</td>
... <td valign="top">Second!</td></tr>
... </table></body><html>
... """)
>>>
>>> soup.findAll('td')
[<td>First!</td>, <td valign="top">Second!</td>]
>>>
>>> soup.findAll('td', valign='top')
[<td valign="top">Second!</td>]
3
juliomalegria

En ajoutant une combinaison de la réponse de Chris Redford et d'Amr, vous pouvez également rechercher un nom d'attribut avec n'importe quelle valeur à l'aide de la commande select:

from bs4 import BeautifulSoup as Soup
html = '<td valign="top">.....</td>\
    <td width="580" valign="top">.......</td>\
    <td>.....</td>'
soup = Soup(html, 'lxml')
results = soup.select('td[valign]')
0
GrazingScientist