Y a-t-il un outil python python pour prendre du code HTML et le tronquer aussi près que possible d'une longueur donnée, mais assurez-vous que l'extrait résultant est bien formé? Par exemple, étant donné à ce code HTML: Il ne produirait pas: p> mais: p> ou au moins: p> Je ne trouve pas un qui fonctionne, bien que j'ai trouvé un qui s'appuie sur pullparser code>, lequel est à la fois obsolète et mort. p> p>
8 Réponses :
Ma première pensée serait utilisée d'un analyseur XML (peut-être Patier SAX de Python ), puis compter probablement les caractères de texte dans chaque élément XML. J'ignorerais le nombre de tags les caractères pour le rendre plus cohérent, mais plus simple, mais soit possible. P>
Alors que j'ai commenté la réponse de Funktku, n'a pas Quelqu'un i> déjà fait cela?
@Jasonfruith oh je vois ce que tu veux dire maintenant - je ne sais pas si c'est vraiment ce commun franchement et c'est assez simple à faire.
Je recommanderais d'abord complètement l'analyse du HTML puis tronquer. Un excellent analyseur HTML pour Python est lxml . Après analyse et tronquage, vous pouvez l'imprimer au format HTML. P>
Mais n'a pas quelqu'un i> déjà fait cela? Je comprends le problème, mais cela semble être tel que quelqu'un doit avoir une solution.
Regardez HTML Tidy à Nettoyage / Reformate / Reindent HTML. P>
Pas la meilleure option, et pas vraiment une chose python.
Il y a quelques bibliothèques Python qui se lient à rangée, vérifiez-la. Je l'utilise pour nettoyer MS-Word HTML Certains utilisateurs collectent en CMS.
Je n'ai également pas précisé que j'utilise Google App Moteur, où je ne peux que introduire des bibliothèques péricit-python.
Si vous utilisez Django Lib, vous pouvez simplement:
import re
def truncate_html_words(s, num):
"""
Truncates html to a certain number of words (not counting tags and comments).
Closes opened tags if they were correctly closed in the given html.
"""
length = int(num)
if length <= 0:
return ''
html4_singlets = ('br', 'col', 'link', 'base', 'img', 'param', 'area', 'hr', 'input')
# Set up regular expressions
re_words = re.compile(r'&.*?;|<.*?>|([A-Za-z0-9][\w-]*)')
re_tag = re.compile(r'<(/)?([^ ]+?)(?: (/)| .*?)?>')
# Count non-HTML words and keep note of open tags
pos = 0
ellipsis_pos = 0
words = 0
open_tags = []
while words <= length:
m = re_words.search(s, pos)
if not m:
# Checked through whole string
break
pos = m.end(0)
if m.group(1):
# It's an actual non-HTML word
words += 1
if words == length:
ellipsis_pos = pos
continue
# Check for tag
tag = re_tag.match(m.group(0))
if not tag or ellipsis_pos:
# Don't worry about non tags or tags after our truncate point
continue
closing_tag, tagname, self_closing = tag.groups()
tagname = tagname.lower() # Element names are always case-insensitive
if self_closing or tagname in html4_singlets:
pass
elif closing_tag:
# Check for match in open tags list
try:
i = open_tags.index(tagname)
except ValueError:
pass
else:
# SGML: An end tag closes, back to the matching start tag, all unclosed intervening start tags with omitted end tags
open_tags = open_tags[i+1:]
else:
# Add it to the start of the open tags list
open_tags.insert(0, tagname)
if words <= length:
# Don't try to close tags if we don't need to truncate
return s
out = s[:ellipsis_pos] + ' ...'
# Close any tags still open
for tag in open_tags:
out += '</%s>' % tag
# Return string
return out
J'utilise Cherrypy, mais cela pourrait valoir la peine d'importer django.utils.text code> si ce n'est pas un coût de démarrage trop ajouté. Je vais l'essayer.
La fonction code> troncate_html_words code> est dans . djangoproject.com/browser/django/trunk/django/utils/... .
Analyse HTML en utilisant des expressions régulières (comme Django en avant) est une idée vraiment, vraiment mauvaise idée.
@slacy: Ce n'est pas analyser HTML, il comptait le nombre de balises ouvertes. C'est un problème beaucoup plus simple.
Ceci servira votre exigence.Un facile à utiliser HTML Parser et Bad Markup Corrector P>
J'ai d'abord regardé ici avant de poser la question. Ce n'est pas mauvais, mais c'est à moi de compter des personnages de contenu et de tronquer au bon point, même si cela fait un bon travail de fixation du balisage une fois que cela est fait.
Je ne pense pas que vous ayez besoin d'un analyseur à part entière - il vous suffit de goûter la chaîne d'entrée dans l'une des suivantes:
Une fois que vous avez un flux de jetons comme celui-ci, il est facile d'utiliser une pile pour garder une trace de ce que les étiquettes ont besoin de fermeture. En fait, je rencontrais ce problème il y a un moment et j'ai écrit une petite bibliothèque pour le faire: P>
https://github.com/eentzel/htmltrunatate.py p>
C'est bien fonctionné pour moi et gère la plupart des caisses de coin, y compris une balise pénétrée arbitrairement imbriquée, de compter des entités de caractère comme un seul Caractère, retourner une erreur sur le balisage mal formé, etc. p>
Il produira: p> sur votre exemple. Cela pourrait peut-être être changé, mais c'est difficile dans le cas général - et si vous essayez de tronquer 10 caractères, mais la balise code> n'est pas fermée pour une autre, par exemple, 300 caractères. ? p> p>
C'est exactement ce que j'ai travaillé et m'a écrit. La seule différence pratique entre le vôtre et la mienne était que j'ai permis de ne pas tronquer que sur les emplacements inter-mots.
J'avais besoin de cela et j'ai mis en œuvre des pauses inter-mots mis en œuvre. C'est très simple, le diff vers l'original est comme 5 lignes - Github.com /enkore/typeflow/blob/master/htmltruncate.py autour de la ligne cinquante
Vous pouvez le faire en une seule ligne avec BeauXoup (en supposant que vous souhaitez tronquer à un certain nombre de caractères source, pas à un certain nombre de caractères de contenu):
from BeautifulSoup import BeautifulSoup
def truncate_html(html, length):
return unicode(BeautifulSoup(html[:length]))
J'ai trouvé la réponse par SLAY très utile et je l'avoue si j'avais la réputation, mais il y avait une chose supplémentaire à noter. Dans mon environnement, j'avais installé HTML5Lib ainsi que BeautifulSoup4. Beautifulsoup a utilisé l'analyseur HTML5LIB et cela a permis d'envelopper mon extrait HTML dans des balises HTML et de corps qui n'est pas ce que je voulais. Pour résoudre ces problèmes, j'ai dit à Beauchsoup d'utiliser l'analyseur Python: p>
Je veux juste laisser les lecteurs savoir: une réponse géniale et très robuste. Fonctionne pour `truncate_html ("
123456789 ", 9)` Retour 12 P> H1> CODE> CODE> CODE>
"Cela produirait:" .. donné quels paramètres? Nombre de caractères dans une rangée? Nombre de dom-éléments, hiérarchie?
Probablement soit un certain nombre de caractères de contenu, soit un certain nombre de caractères HTML. Je ne suis pas pointilleux.