J'essaie d'analyser le contenu de toutes les balises td d'une certaine classe dans une page Web, mais je souhaite avoir un contenu d'espace réservé, même si la balise elle-même n'en a pas. Par exemple, le html contient des balises td comme ceci:
soup.find_all('td', attrs={'class': 'odds bdevtt moneylineodds '})
J'essaie d'obtenir une liste comme ['+134', '-', '-140'] en sortie, donc le nombre d'entrées dans la liste est égal au nombre de balises correspondantes avec '-' comme espace réservé indiquant que la balise était vide. Cependant, ce qui suit ne renvoie que ['+134', '- 140'].
<td class="odds bdevtt moneylineodds " cfg="">+134</td> <td class="odds bdevtt moneylineodds " cfg=""></td> <td class="odds bdevtt moneylineodds " cfg="">-140</td>
3 Réponses :
from bs4 import BeautifulSoup html = """ <td class="odds bdevtt moneylineodds " cfg="">+134</td> <td class="odds bdevtt moneylineodds " cfg=""></td> <td class="odds bdevtt moneylineodds " cfg="">-140</td> """ soup = BeautifulSoup(html,"html.parser") all = [i.text if i.text != "" else "-" for i in soup.find_all('td', attrs={'class': 'odds bdevtt moneylineodds '})] print(all) # output: ['+134', '-', '-140']
Supprimez l'espace de fin de la valeur de l'attribut class
et vous obtiendrez le résultat attendu.
Code:
<td cfg="" class="odds bdevtt moneylineodds">+134</td> <td cfg="" class="odds bdevtt moneylineodds"></td> <td cfg="" class="odds bdevtt moneylineodds">-140</td>
Une solution possible est d'utiliser l'opérateur ou
:
0.7735823660041206 0.8084569670027122 0.776867889042478
Imprime:
txt = '''<td class="odds bdevtt moneylineodds " cfg="">+134</td> <td class="odds bdevtt moneylineodds " cfg=""></td> <td class="odds bdevtt moneylineodds " cfg="">-140</td>''' â from bs4 import BeautifulSoup from timeit import timeit â soup = BeautifulSoup(txt, 'html.parser') â def using_or(): return [td.get_text(strip=True) or '-' for td in soup.select('td.odds.bdevtt.moneylineodds')] â def using_if_else_1(): return [td.text if td.text else '-' for td in soup.select('td.odds.bdevtt.moneylineodds')] â def using_if_else_2(): return [t if (t := td.get_text(strip=True)) else '-' for td in soup.select('td.odds.bdevtt.moneylineodds')] â â t1 = timeit(lambda: using_or(), number=10_000) t2 = timeit(lambda: using_if_else_1(), number=10_000) t3 = timeit(lambda: using_if_else_2(), number=10_000) â print(t1) print(t2) print(t3) â
Certains benchmark rapide:
['+134', '-', '-140']
Ceci imprime:
out = [td.get_text(strip=True) or '-' for td in soup.select('td.odds.bdevtt.moneylineodds')] print(out)
Comme il semble, les solutions sont +/- les mêmes performances.
Intéressant. Savez-vous comment ou
se compare à sinon
en termes d'efficacité?
Merci d'avoir ajouté ça. Je me demande ce qui se passe avec 2 et 3. Peut-être même sur une plus grande taille de test.
@QHarr Je les laisse courir 1_000_000 fois chacun, et les résultats sont 78.19792580400826, 81.93139944702853, 79.0471791360178
, donc oui, la méthode ou
a une avance légère . La méthode 2
est perdante car td.text
est accédé 2 fois.