Supprimer une balise à l'aide de BeautifulSoup mais garder son contenu
Actuellement, j'ai un code qui fait quelque chose comme ceci:
soup = BeautifulSoup(value)
for tag in soup.findAll(True):
if tag.name not in VALID_TAGS:
tag.extract()
soup.renderContents()
Sauf que je ne veux pas jeter le contenu à l'intérieur de la balise incorrecte. Comment puis-je me débarrasser de l'étiquette, mais de garder le contenu à l'intérieur lors de l'appel de la soupe.renderContents()?
Vous devez vous connecter pour publier un commentaire.
La stratégie que j'ai utilisée, c'est de remplacer une étiquette avec son contenu s'ils sont de type
NavigableString
et s'ils ne le sont pas, puis, de manière récursive en eux et de les remplacer leur contenu avecNavigableString
, etc. Essayez ceci:Le résultat est:
J'ai donné la même réponse à une autre question. Il semble venir d'en haut beaucoup.
unicode
des chaînes sur chaque appel.Les versions actuelles de la BeautifulSoup de la bibliothèque ont une méthode non documentée, sur les étiquettes des objets appelés replaceWithChildren(). Donc, vous pourriez faire quelque chose comme ceci:
Dirait qu'il se comporte comme vous le souhaitez et est assez simple code (même si ça fait quelques passes par le DOM, mais cela pourrait facilement être optimisé.)
Bien que cela a déjà été mentoned par d'autres personnes dans les commentaires, je pensais que je poste une réponse complète montrant comment le faire avec Mozilla eau de Javel. Personnellement, je pense que c'est beaucoup plus agréable que d'utiliser BeautifulSoup pour cela.
J'ai une solution plus simple mais je ne sais pas si il ya un inconvénient à cela.
Mise à JOUR: il y a un inconvénient, voir Jesse Dhillon commentaire. Aussi, une autre solution sera d'utiliser Mozilla L'eau de javel au lieu de BeautifulSoup.
Ce sera également l'impression
<div><p>Hello there my friend!</p></div>
comme souhaité.<p>
intacte en casVALID_TAGS = 'b'
depth == 1
. Tentez votre code avec l'exemple dans ma réponse ci-dessus.html
, j'obtiens la même erreur quexralf
(j'utilise la version 3.0.8.1)? Le slacy la solution qui fonctionne pour moi, mais l'inconvénient est que c'est pas possible de spécifier uniquement les étiquettes valides (et peut-être la vitesse).vous pouvez utiliser de la soupe.texte
.le texte supprime toutes les balises et les concaténer l'ensemble du texte.
Vous allez probablement avoir à déplacer la balise enfants d'être des enfants de la balise parent avant d'enlever l'étiquette, est-ce ce que tu veux dire?
Si oui, alors, lors de l'insertion du contenu au bon endroit est un peu difficile, quelque chose comme cela devrait fonctionner:
avec l'exemple de la valeur, il imprime
<div><p>Hello there my friend!</p></div>
comme souhaité.Aucune proposé répondu semblait fonctionner avec BeautifulSoup pour moi. Voici une version qui fonctionne avec BeautifulSoup 3.2.1, et insère également un espace lors de l'adhésion du contenu provenant de différentes étiquettes plutôt que la concaténation de mots.
Exemple:
Utilisation déballer.
Déballer va supprimer un de plusieurs occurrence de la balise et de toujours garder le contenu.
Exemple:
Ici est la meilleure solution sans tracas et de code réutilisable pour filtrer les balises de conserver le contenu.Disons que vous voulez supprimer tous les enfants des balises à l'intérieur de la balise parent et vous voulez juste pour garder le contenu/texte ensuite,vous pouvez tout simplement faire:
C'est elle et vous pouvez être libre avec tous les br ou i b de balises à l'intérieur de la mère de balises et d'obtenir le propre texte.
C'est une vieille question, mais juste pour dire d'une de meilleures façons de le faire. Tout d'abord, BeautifulSoup 3* n'est plus en cours d'élaboration, vous devriez plutôt utiliser BeautifulSoup 4*, dite bs4.
Aussi, lxml vient de la fonction dont vous avez besoin: Nettoyeur de classe a attribut
remove_tags
, que vous pouvez configurer pour les balises qui vont être supprimés, tandis que leur contenu se tire vers le haut dans la balise parent.Ici est un python 3 version imprimable de cette fonction: