Convertir du HTML en texte brut, comment empêcher deux paragraphes de texte de coller ensemble
Cet article vise le problème de l'adhésion du texte lors de la conversion de HTML en texte brut et explique en détail l'utilisation combinée des paramètres separator et strip de get_text dans Beautiful Soup. Fournit des cas de test DOM synthétiques et des codes d'assertion Python complets, y compris les limites au niveau des blocs/en ligne, le traitement des espaces, des méthodes de préparation d'entrée claires et des critères d'acceptation, et fournit des entrées supplémentaires à OmniDoc dans des scénarios de documents complexes.
Lors de la conversion de HTML en texte brut, deux paragraphes de texte restent collés, principalement parce que get_text() est appelé directement sans spécifier de stratégie de séparation. Beautiful Soup assemble tous les nœuds de texte de manière transparente par défaut et les limites entre les éléments au niveau du bloc disparaissent. Ce problème est courant lors de l’utilisation de Beautiful Soup pour extraire du contenu Web.
Au lieu d'utiliser des expressions régulières pour deviner où casser après l'extraction, vous pouvez combiner correctement les paramètres separator et strip pendant l'extraction. Cet article utilise des exemples synthétiques pour démontrer cette méthode, donne un code d'assertion exécutable et explique quelles situations nécessitent une révision manuelle.
Après avoir lu cet article, vous pouvez déterminer si vos résultats d'extraction sont bloqués, utiliser des scripts d'assertion pour vérifier le résultat et clarifier quels problèmes peuvent être résolus par des paramètres et lesquels doivent être modifiés.
Que dois-je faire si je convertis du HTML en texte brut ? Conclusion en une phrase
Utilisez d'abord la combinaison de separator='\n' et strip=True pour appeler get_text(), puis gérez les balises non pertinentes et les problèmes structurels en fonction de la situation de la page.
| votre situation | Pratiques recommandées | raison |
|---|---|---|
| Le texte entre les paragraphes ou les éléments de la liste reste collé | Définissez à la fois separator='\n' et strip=True | le séparateur est responsable de la séparation, la bande supprime les blancs de début et de fin |
| Seul le séparateur est défini | Plus strip=True | Sinon, les espaces en retrait sans signification seront conservés |
| Seule la bande est définie | Ajoutez également un séparateur | Les lignes peuvent encore coller les unes aux autres |
| La page contient des balises non pertinentes telles que script | Supprimez ces balises avant d'appeler | Les paramètres de get_text ne résolvent que le format, pas le nettoyage du contenu. |
| Contient un DOM de table, de canevas ou d'ombre | Modifier la procédure de collecte ou accepter les informations manquantes | Ce type de contenu ne peut pas être résolu en ajustant les paramètres |
Pièges et sémantique des paramètres du comportement par défaut
Pourquoi ça colle ?
La méthode get_text() accepte deux paramètres clés : separator et strip. Si aucun paramètre n'est transmis, il connectera directement tous les nœuds de texte dans l'arborescence des balises.
Ce comportement par défaut est très problématique pour les éléments de niveau bloc tels que div, p et li. Les sauts de ligne et les retraits dans le code source HTML sont souvent transformés en chaînes vides ou ignorés après l'analyse, et les frontières sémantiques disparaissent.
À quoi servent le séparateur et la bande ?
- séparateur : Définit l'insertion entre les nœuds de texte. Le réglage sur
'\n'est une pratique courante, mais pas parfaite. Si le HTML est profondément imbriqué, le retour à la ligne global peut entraîner un grand nombre de lignes vides. - strip : contrôlez s'il faut supprimer l'espace vide au début et à la fin de chaque fragment de texte. Lorsque
strip=True, Beautiful Soup exécutera d'abord.strip()sur chaque NavigableString indépendante, puis utilisera un séparateur pour les séparer.
Par exemple, <p> Hello </p> obtiendra un Hello propre au lieu de \n Hello \n avec une sortie de données modifiées.
Les deux doivent être utilisés ensemble :
- Utiliser uniquement un séparateur sans bande conservera les espaces en retrait dénués de sens.
- Avec seulement une bande et sans séparateur, une seule ligne sera propre, mais il peut toujours y avoir une adhérence entre les lignes.
Pour plus de descriptions de paramètres, veuillez vous référer à Documentation officielle de Beautiful Soup : get_text().
Cas de test des limites du DOM synthétique
Pour valider la logique d'extraction, des échantillons HTML synthétiques contenant des problèmes de limites typiques doivent être construits au lieu de s'appuyer sur de vraies pages Web instables. Les cas de test suivants couvrent trois situations : l'adhésion d'éléments au niveau du bloc, l'espacement des éléments en ligne et l'espace blanc excessif.
Échantillon d'entrée (exemple synthétique) :
<div>
<p>第一段文字</p>
<p>第二段文字<span>内联补充</span></p>
<ul>
<li> 列表项A </li>
<li>列表项B</li>
</ul>
</div>
Sortie correcte attendue :
第一段文字
第二段文字
内联补充
列表项A
列表项B
Il convient de noter que separator='\n' agit sur les nœuds de texte extraits et ne générera pas automatiquement des sauts de ligne doubles basés sur des balises au niveau du bloc. Il doit y avoir des sauts de ligne clairs entre les paragraphes et les éléments de la liste, et les espaces supplémentaires avant et après les éléments de la liste doivent être supprimés. "Deuxième texte" et "Supplément en ligne" sont situés dans des étiquettes différentes et sont des nœuds de texte, ils seront donc séparés par des délimiteurs.
Erreurs et saisie des limites
Si l'entrée devient <p>End</p><script>alert(1)</script><p>Start</p> et que la balise de script n'est pas filtrée, la sortie contiendra alert(1). Cela est vrai même si le séparateur est défini. L'inclusion ou non des nœuds de script dans le texte dépend de l'analyseur et du type de nœud.
La bonne façon de gérer cela consiste à utiliser soup.find_all('script') pour supprimer les balises non pertinentes avant d'appeler get_text, ou pour ignorer des types de balises spécifiques lors du parcours. Les paramètres de get_text résolvent uniquement le problème de format, pas le problème de nettoyage du contenu.
Implémentation Python et vérification des assertions
Le code ci-dessous crée l'exemple ci-dessus en mémoire et effectue une vérification déterministe. L'exemple dépend de beautifulsoup4 et la version 4.9.0 et supérieure est recommandée.
Pour tester des fichiers externes, veuillez d'abord enregistrer le HTML au format UTF-8, puis utiliser open('file.html', encoding='utf-8') pour le lire afin d'éviter des erreurs d'encodage provoquant des exceptions d'analyse. Le code ne contient aucune requête réseau et est complètement autonome.
from bs4 import BeautifulSoup
# 合成示例:模拟常见的HTML文本边界问题
html_content = """
<div>
<p>第一段文字</p>
<p>第二段文字<span>内联补充</span></p>
<ul>
<li> 列表项A </li>
<li>列表项B</li>
</ul>
</div>
"""
soup = BeautifulSoup(html_content, 'html.parser')
# 关键配置:separator定义边界,strip清理碎片空白
text_result = soup.get_text(separator='\n', strip=True)
# 过滤空行以获得干净的语义行
lines = [line for line in text_result.split('\n') if line]
# 验收断言:确保边界清晰且无脏数据
assert lines[0] == '第一段文字', f"段落粘连或内容错误: {lines[0]}"
assert lines[1] == '第二段文字', "块级元素间未正确分隔"
assert lines[2] == '内联补充', "内联元素文本节点被错误合并"
assert lines[3] == '列表项A', f"列表项前置空格未清除: '{lines[3]}'"
assert lines[4] == '列表项B', "列表项间边界丢失"
print("提取结果预览:")
for i, line in enumerate(lines):
print(f"{i}: [{line}]")
Le résultat attendu de ce code est cinq lignes de texte clair. Si votre environnement génère plus de lignes vides, cela signifie qu'il existe des nœuds NavigableString vierges dans le DOM qui n'ont pas été supprimés. Il s'agit d'un comportement normal de html.parser et peut être filtré avec des compréhensions de liste après la division.
Ce code sert uniquement à démontrer le principe de combinaison de paramètres et ne doit pas être utilisé directement sur des pages complexes dans l'environnement de production.
📊 Comparaison de base
| plan | Effet | limites |
|---|---|---|
Utilisez uniquement separator='\n' | Il y a des sauts de ligne entre les blocs | Gardez les espaces en retrait, un grand nombre de lignes vides peuvent apparaître lorsque l'imbrication est profonde |
Utilisez uniquement strip=True | Nettoyer le début et la fin de chaque paragraphe | Les lignes peuvent encore coller les unes aux autres |
| Utilisez les deux en même temps | Prise en compte à la fois de la séparation et de la suppression des espaces | Les balises non pertinentes doivent toujours être supprimées avant l'extraction |
| Utilisez des expressions régulières pour deviner la nouvelle ligne après l'extraction | Apparemment flexible | Non recommandé, la priorité doit être donnée à la combinaison correcte des paramètres lors de l'extraction |
Critères d'acceptation et limites de révision manuelle
L'extraction automatisée ne peut pas permettre une restauration visuelle à 100 %. Le tableau suivant indique comment faire la distinction entre les situations « code réparable » et « nécessite une intervention humaine ». Le jugement est basé sur la structure du DOM et non sur un sentiment subjectif.
| observer | ce qu'il faut faire | il ne faut pas en déduire |
|---|---|---|
| Séparation des nœuds en ligne | Vérifiez si la phrase est divisée | Le délimiteur agit sur les nœuds de texte |
| Aplatissement du tableau | Conserver la structure des lignes et des colonnes pour un traitement séparé | Vous ne pouvez pas uniquement compter sur get_text |
| Dessiner du contenu dynamiquement | Identifier les lacunes de collecte | L'analyse statique n'est pas égale au rendu du navigateur |
Portée explicite d'inapplicabilité : Beautiful Soup ne peut pas obtenir d'informations valides lorsque le code HTML contient une grande quantité de texte généré par des pseudo-éléments CSS, du contenu rendu par Canvas ou Shadow DOM. À ce stade, le débogage des paramètres ne doit pas continuer, mais le schéma d'acquisition doit être modifié ou les informations manquantes doivent être acceptées.
🎯 Quelle méthode vous convient ?
si tu……
Besoin d'extraire le texte brut des paragraphes et des éléments de liste
Définissez separator='\n' et strip=True et vérifiez la sortie avec un script d'assertion.
Il y a de nombreuses balises de script ou de style dans la page
Supprimez ces balises avant d'appeler get_text et ne vous attendez pas à ce que les paramètres résolvent les problèmes de contenu.
Nécessité de conserver la structure des lignes et des colonnes du tableau
Ne comptez pas uniquement sur get_text, gérez la structure de la table séparément.
La page repose sur le rendu du navigateur ou Shadow DOM
Modifiez le plan de collecte ou enregistrez clairement les écarts de collecte lors de la réception.
❓ Questions fréquemment posées (FAQ)
1. Est-il suffisant de simplement définir un séparateur ?
pas assez. Définir uniquement un séparateur préservera les espaces d'indentation dénués de sens, et strip=True devra également être ajouté.
2. Pourquoi y a-t-il des lignes vides dans la sortie ?
Il peut y avoir des nœuds NavigableString vides dans le DOM qui n'ont pas été supprimés. Il s'agit d'un comportement normal de html.parser et peut être filtré avec des compréhensions de liste après la division.
3. Pourquoi la balise script apparaît-elle dans les résultats ?
Les paramètres de get_text résolvent uniquement le problème de format. Doit être supprimé avec soup.find_all('script') avant l'appel, ou ignoré pendant le parcours.
4. Comment vérifier si le résultat de l'extraction est correct ?
Construisez un ensemble de tests synthétiques de 5 à 10 cas extrêmes typiques et exécutez des scripts d'assertion. Si le taux de réussite est inférieur aux attentes, vérifiez si vous devez prétraiter le DOM avant de l'extraire.
📝Résumé
Le cœur du problème d’adhésion réside dans la combinaison des paramètres lors de l’extraction, et non dans la réparation des cordes après l’extraction. Parcourez d’abord les échantillons et les assertions synthétiques, puis traitez les balises non pertinentes et les problèmes structurels dans la page réelle.


