1
votes

Rechercher des données dans des balises HTML à l'aide de Python

J'ai le code HTML suivant que j'essaie de récupérer sur un site Web:

soup = BeautifulSoup(url, "html.parser")
table = soup.select('#Net Taxes Due')

cells = table.find_next_siblings('td')
cells = [ele.text.strip() for ele in cells]

df = pd.DataFrame(np.array(cells))

print(df)

Ce que j'essaie d'accomplir, c'est de rechercher sur la page le texte "Taxes nettes dues" dans la balise, trouvez les frères et sœurs de la balise et envoyez les résultats dans un cadre de données Pandas.

J'ai le code suivant:

<td>Net Taxes Due<td>
<td class="value-column">$2,370.00</td>
<td class="value-column">$2,408.00</td>

I ' J'ai parcouru le Web à la recherche d'une solution et je n'arrive pas à trouver quelque chose. Nous apprécions toute aide.

Merci!


0 commentaires

5 Réponses :


0
votes

Votre appel .select () n'est pas correct. # dans un sélecteur est utilisé pour faire correspondre l'ID d'un élément, pas son contenu textuel, donc #Net signifie rechercher un élément avec id = "Net" . Les espaces dans un sélecteur permettent de rechercher des descendants correspondant à chaque sélecteur successif. Ainsi, #Net Taxes Due recherche quelque chose comme:

table = soup.find(string="Net Taxes Due")

Pour rechercher un élément contenant une chaîne spécifique, utilisez .find () avec le mot-clé string :

<div id="Net">
    <taxes>
        <due>...</due>
    </taxes>
</div>


3 commentaires

Merci. Je lance cela en utilisant la chaîne; cependant, j'obtiens une erreur lorsque j'essaye de trouver les frères et sœurs de cette balise. cells = table.find_next_siblings ('td') AttributeError: l'objet 'NoneType' n'a pas d'attribut 'find_next_siblings'


Cela signifie qu'il ne trouve pas l'élément Net Taxes Due , donc find () renvoie None .


Était-ce avant ou après avoir corrigé l'URL?



0
votes

En supposant qu'un tableau HTML réel est impliqué:

<html>
<table>
<tr>
<td>Net Taxes Due</td>
<td class="value-column">$2,370.00</td>
<td class="value-column">$2,408.00</td>
</tr>
</table>
</html>

soup = BeautifulSoup(url, "html.parser")
table = soup.find('tr')
df = [x.text for x in table.findAll('td', {'class':'value-column'})]


1 commentaires

Recherchez la compréhension de la liste. Dans ce cas, x représente chaque balise individuelle trouvée par la méthode findAll.



1
votes

Dans ce qui suit, je m'attendais à utiliser les indices 1 et 2 mais 2 et 3 semblent fonctionner avec lxml.html et xpath

import requests
from lxml.html import fromstring
# url = ''
# tree = html.fromstring( requests.get(url).content)
h = '''
<td>Net Taxes Due<td>
<td class="value-column">$2,370.00</td>
<td class="value-column">$2,408.00</td>

'''
tree = fromstring(h)
links = [link.text for link in tree.xpath('//td[text() = "Net Taxes Due"]/following-sibling::td[2] | //td[text() = "Net Taxes Due"]/following-sibling::td[3]' )]
print(links)


0 commentaires

0
votes

Assurez-vous d'ajouter le nom de la balise avec votre chaîne de recherche. Voici comment vous pouvez le faire:

from bs4 import BeautifulSoup

htmldoc = """
<tr>
    <td>Net Taxes Due</td>
    <td class="value-column">$2,370.00</td>
    <td class="value-column">$2,408.00</td>
</tr>
"""    
soup = BeautifulSoup(htmldoc, "html.parser")
item = soup.find('td',text='Net Taxes Due').find_next_sibling("td")
print(item)


3 commentaires

J'obtiens l'erreur suivante: l'objet 'NoneType' n'a pas d'attribut 'find_next_sibling'


Ensuite, vous devez gérer les choses de la mauvaise manière. Comme preuve de concept, essayez d'exécuter l'extrait de code ci-dessus.


Merci! Votre solution fonctionne parfaitement. Il s'avère que je suis un idiot et que j'ai eu une erreur dans l'URL d'où je tirais. Pas étonnant qu'il ne renvoie aucune valeur ...



0
votes

Cela devrait fonctionner. Si vous utilisez bs4 4.7.0, vous «pouvez» utiliser select. Mais si vous utilisez une version plus ancienne ou préférez simplement l'interface de recherche, vous pouvez l'utiliser. Fondamentalement, comme indiqué précédemment, vous ne pouvez pas référencer le contenu avec # , c'est-à-dire un identifiant.

['$2,370.00', '$2,408.00']
['$2,370.00', '$2,408.00']

Vous obtiendriez ceci

import bs4

markup = """
<td>Net Taxes Due</td>
<td class="value-column">$2,370.00</td>
<td class="value-column">$2,408.00</td>
"""

# Version 4.7.0
soup = bs4.BeautifulSoup(markup, "html.parser")
cells = soup.select('td:contains("Net Taxes Due") ~ td.value-column')
cells = [ele.text.strip() for ele in cells]
print(cells)

# Version < 4.7.0 or if you prefer find
soup = bs4.BeautifulSoup(markup, "html.parser")
cells = soup.find('td', text="Net Taxes Due").find_next_siblings('td')
cells = [ele.text.strip() for ele in cells]
print(cells)


0 commentaires