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!
5 Réponses :
Votre appel Pour rechercher un élément contenant une chaîne spécifique, utilisez .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")
.find ()
avec le mot-clé string
: <div id="Net">
<taxes>
<due>...</due>
</taxes>
</div>
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?
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'})]
Recherchez la compréhension de la liste. Dans ce cas, x représente chaque balise individuelle trouvée par la méthode findAll.
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)
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)
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 ...
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)