web-dev-qa-db-fra.com

Supprimer le code HTML des chaînes en Python

from mechanize import Browser
br = Browser()
br.open('http://somewebpage')
html = br.response().readlines()
for line in html:
  print line

Lors de l'impression d'une ligne dans un fichier HTML, j'essaie de trouver un moyen d'afficher uniquement le contenu de chaque élément HTML et non le formatage lui-même. S'il trouve '<a href="whatever.com">some text</a>', il n'imprimera que 'du texte', '<b>hello</b>' affiche 'bonjour', etc. Comment procéder?

237
directedition

J'ai toujours utilisé cette fonction pour supprimer les balises HTML, car elle ne nécessite que la stdlib Python:

Sur Python 2

from HTMLParser import HTMLParser

class MLStripper(HTMLParser):
    def __init__(self):
        self.reset()
        self.fed = []
    def handle_data(self, d):
        self.fed.append(d)
    def get_data(self):
        return ''.join(self.fed)

def strip_tags(html):
    s = MLStripper()
    s.feed(html)
    return s.get_data()

Pour Python 3

from html.parser import HTMLParser

class MLStripper(HTMLParser):
    def __init__(self):
        self.reset()
        self.strict = False
        self.convert_charrefs= True
        self.fed = []
    def handle_data(self, d):
        self.fed.append(d)
    def get_data(self):
        return ''.join(self.fed)

def strip_tags(html):
    s = MLStripper()
    s.feed(html)
    return s.get_data()

Note: cela ne fonctionne que pour 3.1. Pour 3.2 ou plus, vous devez appeler la fonction init de la classe parente. Voir Utiliser HTMLParser en Python 3.2

378
Eloff

Je n'ai pas beaucoup réfléchi aux cas qui vont lui manquer, mais vous pouvez faire une regex simple:

re.sub('<[^<]+?>', '', text)

Pour ceux qui ne comprennent pas les expressions rationnelles, ceci recherche une chaîne <...>, où le contenu interne est composé d'un ou plusieurs caractères (+) qui ne sont pas un <. Le ? signifie qu'il correspondra à la plus petite chaîne qu'il peut trouver. Par exemple, si l'on donne <p>Hello</p>, il fera correspondre <'p> et </p> séparément avec le ?. Sans cela, il correspondra à la chaîne entière <..Hello..>.

Si le < non-tag apparaît en HTML (par exemple, 2 < 3), il devrait être écrit sous la forme d'une séquence d'échappement &... de toute façon, de sorte que le ^< puisse être inutile.

132
mmmdreg

Pourquoi vous le faites tous à la dure? Vous pouvez utiliser la fonction BeautifulSoup get_text().

from bs4 import BeautifulSoup

html_str = '''
<td><a href="http://www.fakewebsite.com">Please can you strip me?</a>
<br/><a href="http://www.fakewebsite.com">I am waiting....</a>
</td>
'''
soup = BeautifulSoup(html_str)

print(soup.get_text()) 
#or via attribute of Soup Object: print(soup.text)
33
Aminah Nuraini

J'avais besoin d'un moyen de décaper les balises et décoder les entités HTML en texte brut. La solution suivante est basée sur la réponse d'Eloff (que je n'ai pas pu utiliser car elle supprime les entités).

from HTMLParser import HTMLParser
import htmlentitydefs

class HTMLTextExtractor(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.result = [ ]

    def handle_data(self, d):
        self.result.append(d)

    def handle_charref(self, number):
        codepoint = int(number[1:], 16) if number[0] in (u'x', u'X') else int(number)
        self.result.append(unichr(codepoint))

    def handle_entityref(self, name):
        codepoint = htmlentitydefs.name2codepoint[name]
        self.result.append(unichr(codepoint))

    def get_text(self):
        return u''.join(self.result)

def html_to_text(html):
    s = HTMLTextExtractor()
    s.feed(html)
    return s.get_text()

Un test rapide:

html = u'<a href="#">Demo <em>(&not; \u0394&#x03b7;&#956;&#x03CE;)</em></a>'
print repr(html_to_text(html))

Résultat:

u'Demo (\xac \u0394\u03b7\u03bc\u03ce)'

La gestion des erreurs:

  • Une structure HTML non valide peut provoquer un HTMLParseError .
  • Les entités HTML nommées non valides (telles que &#apos;, qui est valide en XML et XHTML, mais pas en HTML pur) provoqueront une exception ValueError.
  • Les entités HTML numériques spécifiant des points de code situés en dehors de la plage Unicode et acceptées par Python (telles que, sur certains systèmes, les caractères situés en dehors du Plan multilingue de base ) généreront une exception ValueError.

Note de sécurité: Ne confondez pas la suppression HTML (conversion de HTML en texte brut) avec la purification de HTML (conversion du texte brut en HTML). Cette réponse supprimera le HTML et décodera les entités en texte brut - cela ne sécurisera pas l'utilisation du résultat dans un contexte HTML.

Exemple: &lt;script&gt;alert("Hello");&lt;/script&gt; sera converti en <script>alert("Hello");</script>, comportement correct à 100%, mais évidemment insuffisant si le texte brut résultant est inséré tel quel dans une page HTML.

La règle n’est pas difficile: à tout moment vous insérez une chaîne de texte en clair dans la sortie HTML, vous devez toujours HTML l’échapper (avec cgi.escape(s, True)), même si vous "savez" que cela ne contient pas HTML (par exemple parce que vous avez supprimé le contenu HTML).

(Cependant, l'OP a demandé si le résultat était imprimé sur la console, auquel cas aucun échappement HTML n'est nécessaire.)

Version Python 3.4+: (avec doctest!)

import html.parser

class HTMLTextExtractor(html.parser.HTMLParser):
    def __init__(self):
        super(HTMLTextExtractor, self).__init__()
        self.result = [ ]

    def handle_data(self, d):
        self.result.append(d)

    def get_text(self):
        return ''.join(self.result)

def html_to_text(html):
    """Converts HTML to plain text (stripping tags and converting entities).
    >>> html_to_text('<a href="#">Demo<!--...--> <em>(&not; \u0394&#x03b7;&#956;&#x03CE;)</em></a>')
    'Demo (\xac \u0394\u03b7\u03bc\u03ce)'

    "Plain text" doesn't mean result can safely be used as-is in HTML.
    >>> html_to_text('&lt;script&gt;alert("Hello");&lt;/script&gt;')
    '<script>alert("Hello");</script>'

    Always use html.escape to sanitize text before using in an HTML context!

    HTMLParser will do its best to make sense of invalid HTML.
    >>> html_to_text('x < y &lt z <!--b')
    'x < y < z '

    Unrecognized named entities are included as-is. '&apos;' is recognized,
    despite being XML only.
    >>> html_to_text('&nosuchentity; &apos; ')
    "&nosuchentity; ' "
    """
    s = HTMLTextExtractor()
    s.feed(html)
    return s.get_text()

Notez que HTMLParser a été amélioré dans Python 3 (moins de code et une meilleure gestion des erreurs).

27
Søren Løvborg

Version courte!

import re, cgi
tag_re = re.compile(r'(<!--.*?-->|<[^>]*>)')

# Remove well-formed tags, fixing mistakes by legitimate users
no_tags = tag_re.sub('', user_input)

# Clean up anything else by escaping
ready_for_web = cgi.escape(no_tags)

Source Regex: MarkupSafe . Leur version gère aussi les entités HTML, alors que cette rapide ne le fait pas.

Pourquoi ne puis-je pas simplement décaper les étiquettes et les laisser?

C'est une chose de garder les gens de <i>italicizing</i> choses, sans laisser is flotter. Mais c’est une autre chose de prendre des entrées arbitraires et de les rendre complètement inoffensives. La plupart des techniques sur cette page laissent intacts les commentaires non fermés (<!--) et les crochets angulaires ne faisant pas partie des balises (blah <<<><blah). La version HTMLParser peut même laisser des balises complètes à l'intérieur, si elles se trouvent dans un commentaire non fermé.

Et si votre modèle est {{ firstname }} {{ lastname }}? firstname = '<a' et lastname = 'href="http://evil.com/">' seront utilisés par chaque strip-teaseuse sur cette page (sauf @Medeiros!), car ce ne sont pas des balises complètes. Supprimer les balises HTML normales ne suffit pas.

La version strip_tags de Django, une version améliorée (voir en-tête suivante) de la première réponse à cette question, donne l'avertissement suivant:

Absolument aucune garantie n'est fournie quant à la sécurité de la chaîne résultante en HTML. Donc, ne marquez JAMAIS en toute sécurité le résultat d'un appel strip_tags sans d'abord l'échapper, par exemple avec escape().

Suivez leurs conseils!

Pour supprimer les balises avec HTMLParser, vous devez l'exécuter plusieurs fois.

Il est facile de contourner la première réponse à cette question.

Regardez cette chaîne ( source et discussion ):

<img<!-- --> src=x onerror=alert(1);//><!-- -->

La première fois que HTMLParser le voit, il ne peut pas dire que le <img...> est une balise. Il semble cassé, donc HTMLParser ne s'en débarrasse pas. Il ne prend que le <!-- comments -->, vous laissant avec

<img src=x onerror=alert(1);//>

Ce problème a été révélé au projet Django en mars 2014. Leur ancien strip_tags était essentiellement le même que la réponse principale à cette question. Leur nouvelle version l'exécute en boucle jusqu'à ce qu'il ne soit plus exécuté ne change pas la chaîne:

# _strip_once runs HTMLParser once, pulling out just the text of all the nodes.

def strip_tags(value):
    """Returns the given HTML with all tags stripped."""
    # Note: in typical case this loop executes _strip_once once. Loop condition
    # is redundant, but helps to reduce number of executions of _strip_once.
    while '<' in value and '>' in value:
        new_value = _strip_once(value)
        if len(new_value) >= len(value):
            # _strip_once was not able to detect more tags
            break
        value = new_value
    return value

Bien sûr, rien de tout cela n’est un problème si vous échappez toujours au résultat de strip_tags().

Mise à jour du 19 mars 2015: Il existait un bogue dans les versions de Django antérieures à 1.4.20, 1.6.11, 1.7.7 et 1.8c1. Ces versions pourraient entrer dans une boucle infinie dans la fonction strip_tags (). La version corrigée est reproduite ci-dessus. Plus de détails ici .

Bonnes choses à copier ou à utiliser

Mon exemple de code ne gère pas les entités HTML, contrairement aux versions packagées de Django et MarkupSafe.

Mon exemple de code est tiré de l'excellente bibliothèque/ MarkupSafe pour la prévention des scripts entre sites. C'est pratique et rapide (avec C accélérations à sa version native de Python). Il est inclus dans Google App Engine , et utilisé par Jinja2 (2.7 et plus) , Mako, Pylons, etc. Cela fonctionne facilement avec les modèles Django de Django 1.7.

Les strip_tags de Django et les autres utilitaires HTML d'une version récente sont bons, mais je les trouve moins pratiques que MarkupSafe. Ils sont assez autonomes, vous pouvez copier ce dont vous avez besoin depuis ce fichier .

Si vous devez effacer presque toutes les balises, la bibliothèque Bleach est bonne. Vous pouvez le faire appliquer des règles telles que "mes utilisateurs peuvent mettre des choses en italique, mais ils ne peuvent pas créer d'iframes".

Comprenez les propriétés de votre décapant de balises! Exécutez des tests fuzz dessus! Voici le code J'avais l'habitude de faire des recherches pour cette réponse.

note timorée _ La question elle-même concerne l'impression sur la console, mais il s'agit du premier résultat de Google pour "python strip html from string", c'est pourquoi cette réponse concerne 99% du Web.

27
rescdsk

Il y a un moyen simple de faire ça:

def remove_html_markup(s):
    tag = False
    quote = False
    out = ""

    for c in s:
            if c == '<' and not quote:
                tag = True
            Elif c == '>' and not quote:
                tag = False
            Elif (c == '"' or c == "'") and tag:
                quote = not quote
            Elif not tag:
                out = out + c

    return out

L'idée est expliquée ici: http://youtu.be/2tu9LTDujbw

Vous pouvez le voir fonctionner ici: http://youtu.be/HPkNPcYed9M?t=35s

PS - Si vous êtes intéressé par le cours (sur le débogage intelligent avec python), je vous donne un lien: http://www.udacity.com/overview/Course/cs259/CourseRev/1 . C'est gratuit! 

De rien! :)

18
Medeiros

Si vous devez conserver les entités HTML (c'est-à-dire &amp;), j'ai ajouté la méthode "handle_entityref" à La réponse d'Eloff .

from HTMLParser import HTMLParser

class MLStripper(HTMLParser):
    def __init__(self):
        self.reset()
        self.fed = []
    def handle_data(self, d):
        self.fed.append(d)
    def handle_entityref(self, name):
        self.fed.append('&%s;' % name)
    def get_data(self):
        return ''.join(self.fed)

def html_to_text(html):
    s = MLStripper()
    s.feed(html)
    return s.get_data()
16
Robert

Si vous voulez supprimer toutes les balises HTML, la méthode la plus simple que j'ai trouvée consiste à utiliser BeautifulSoup:

from bs4 import BeautifulSoup  # Or from BeautifulSoup import BeautifulSoup

def stripHtmlTags(htmlTxt):
    if htmlTxt is None:
            return None
        else:
            return ''.join(BeautifulSoup(htmlTxt).findAll(text=True)) 

J'ai essayé le code de la réponse acceptée, mais le message "RuntimeError: profondeur de récursion maximale dépassée" n'a pas été utilisé, ce qui n'est pas arrivé avec le bloc de code ci-dessus.

12
Vasilis

Une solution basée sur lxml.html - (lxml est une bibliothèque native et est donc beaucoup plus rapide que toute solution python pure). 

from lxml import html
from lxml.html.clean import clean_html

tree = html.fromstring("""<span class="item-summary">
                            Detailed answers to any questions you might have
                        </span>""")

print(clean_html(tree).strip())

# >>> Detailed answers to any questions you might have

Voir aussi http://lxml.de/lxmlhtml.html#cleaning-up-html pour savoir ce que fait exactement le fichier lxml.cleaner. 

Si vous avez besoin de plus de contrôle sur ce qui est exactement assaini avant de convertir en texte, vous pouvez utiliser le lxml Cleaner explicitement en passant les options de votre choix dans le constructeur, par exemple: 

cleaner = Cleaner(page_structure=True,
                  meta=True,
                  embedded=True,
                  links=True,
                  style=True,
                  processing_instructions=True,
                  inline_style=True,
                  scripts=True,
                  javascript=True,
                  comments=True,
                  frames=True,
                  forms=True,
                  annoying_tags=True,
                  remove_unknown_tags=True,
                  safe_attrs_only=True,
                  safe_attrs=frozenset(['src','color', 'href', 'title', 'class', 'name', 'id']),
                  remove_tags=('span', 'font', 'div')
                  )
sanitized_html = cleaner.clean_html(unsafe_html)
9
ccpizza

Le paquet Beautiful Soup fait cela immédiatement pour vous. 

from bs4 import BeautifulSoup

soup = BeautifulSoup(html)
text = soup.get_text()
print(text)
6
runawaykid

Vous pouvez utiliser un analyseur HTML différent ( comme lxml ou Beautiful Soup ) - offrant des fonctions permettant d’extraire uniquement du texte. Ou, vous pouvez exécuter une expression régulière sur votre ligne qui supprime les balises. Voir http://www.amk.ca/python/howto/regex/ pour plus d'informations.

2
Jason Coon

Pour un projet, j'avais besoin de supprimer HTML, mais aussi css et js. J'ai donc fait une variante de la réponse d'Eloff:

class MLStripper(HTMLParser):
    def __init__(self):
        self.reset()
        self.strict = False
        self.convert_charrefs= True
        self.fed = []
        self.css = False
    def handle_starttag(self, tag, attrs):
        if tag == "style" or tag=="script":
            self.css = True
    def handle_endtag(self, tag):
        if tag=="style" or tag=="script":
            self.css=False
    def handle_data(self, d):
        if not self.css:
            self.fed.append(d)
    def get_data(self):
        return ''.join(self.fed)

def strip_tags(html):
    s = MLStripper()
    s.feed(html)
    return s.get_data()
1
mousetail

Une adaptation en python 3 de la réponse de søren-løvborg

from html.parser import HTMLParser
from html.entities import html5

class HTMLTextExtractor(HTMLParser):
    """ Adaption of http://stackoverflow.com/a/7778368/196732 """
    def __init__(self):
        super().__init__()
        self.result = []

    def handle_data(self, d):
        self.result.append(d)

    def handle_charref(self, number):
        codepoint = int(number[1:], 16) if number[0] in (u'x', u'X') else int(number)
        self.result.append(unichr(codepoint))

    def handle_entityref(self, name):
        if name in html5:
            self.result.append(unichr(html5[name]))

    def get_text(self):
        return u''.join(self.result)

def html_to_text(html):
    s = HTMLTextExtractor()
    s.feed(html)
    return s.get_text()
1
CpILL

Les solutions avec HTML-Parser sont toutes cassables si elles ne fonctionnent qu'une seule fois:

html_to_text('<<b>script>alert("hacked")<</b>/script>

résulte en:

<script>alert("hacked")</script>

ce que vous avez l'intention d'empêcher. Si vous utilisez un analyseur HTML, comptez les balises jusqu'à ce que zéro soit remplacé:

from HTMLParser import HTMLParser

class MLStripper(HTMLParser):
    def __init__(self):
        self.reset()
        self.fed = []
        self.containstags = False

    def handle_starttag(self, tag, attrs):
       self.containstags = True

    def handle_data(self, d):
        self.fed.append(d)

    def has_tags(self):
        return self.containstags

    def get_data(self):
        return ''.join(self.fed)

def strip_tags(html):
    must_filtered = True
    while ( must_filtered ):
        s = MLStripper()
        s.feed(html)
        html = s.get_data()
        must_filtered = s.has_tags()
    return html
1
Falk Nisius

Ceci est une solution rapide et peut être encore plus optimisé, mais cela fonctionnera bien. Ce code remplacera toutes les balises non vides par "" et supprimera toutes les balises HTML d'un texte d'entrée donné. Vous pourrez l'exécuter à l'aide de

    #!/usr/bin/python
import sys

def replace(strng,replaceText):
    rpl = 0
    while rpl > -1:
        rpl = strng.find(replaceText)
        if rpl != -1:
            strng = strng[0:rpl] + strng[rpl + len(replaceText):]
    return strng


lessThanPos = -1
count = 0
listOf = []

try:
    #write File
    writeto = open(sys.argv[2],'w')

    #read file and store it in list
    f = open(sys.argv[1],'r')
    for readLine in f.readlines():
        listOf.append(readLine)         
    f.close()

    #remove all tags  
    for line in listOf:
        count = 0;  
        lessThanPos = -1  
        lineTemp =  line

            for char in lineTemp:

            if char == "<":
                lessThanPos = count
            if char == ">":
                if lessThanPos > -1:
                    if line[lessThanPos:count + 1] != '<>':
                        lineTemp = replace(lineTemp,line[lessThanPos:count + 1])
                        lessThanPos = -1
            count = count + 1
        lineTemp = lineTemp.replace("&lt","<")
        lineTemp = lineTemp.replace("&gt",">")                  
        writeto.write(lineTemp)  
    writeto.close() 
    print "Write To --- >" , sys.argv[2]
except:
    print "Help: invalid arguments or exception"
    print "Usage : ",sys.argv[0]," inputfile outputfile"
1
kiran Mohan

J'ai utilisé la réponse d'Eloff avec succès pour Python 3.1 [merci beaucoup!].

Je suis passé à Python 3.2.3 et j'ai rencontré des erreurs. 

La solution, fournie ici grâce au répondeur Thomas K, consiste à insérer super().__init__() dans le code suivant:

def __init__(self):
    self.reset()
    self.fed = []

... afin de le faire ressembler à ceci:

def __init__(self):
    super().__init__()
    self.reset()
    self.fed = []

... et cela fonctionnera pour Python 3.2.3.

Encore une fois, merci à Thomas K pour le correctif et pour le code original d'Eloff fourni ci-dessus!

1
MilesNielsen

Voici une solution similaire à la réponse actuellement acceptée ( https://stackoverflow.com/a/925630/95989 ), sauf qu'elle utilise directement la classe interne HTMLParser (c'est-à-dire sans sous-classement), ce qui la rend nettement plus concise. :

 def strip_html (text): 
 parties = [] 
 analyseur = HTMLParser () 
 parser.handle_data = parts.append 
 parser.feed (text) 
 retour '' .join (parts) 
1
Richard

Vous pouvez écrire votre propre fonction:

def StripTags(text):
     finished = 0
     while not finished:
         finished = 1
         start = text.find("<")
         if start >= 0:
             stop = text[start:].find(">")
             if stop >= 0:
                 text = text[:start] + text[start+stop+1:]
                 finished = 0
     return text
0
Yuda Prawira

Voici ma solution pour Python 3.

import html
import re

def html_to_txt(html_text):
    ## unescape html
    txt = html.unescape(html_text)
    tags = re.findall("<[^>]+>",txt)
    print("found tags: ")
    print(tags)
    for tag in tags:
        txt=txt.replace(tag,'')
    return txt

Pas sûr que ce soit parfait, mais résolu mon cas d'utilisation et semble simple. 

0
John Loutzenhiser

Code simple !. Cela supprimera tout type de balises et de contenu à l'intérieur.

def rm(s):
    start=False
    end=False
    s=' '+s
    for i in range(len(s)-1):
        if i<len(s):
            if start!=False:
                if s[i]=='>':
                    end=i
                    s=s[:start]+s[end+1:]
                    start=end=False
            else:
                if s[i]=='<':
                    start=i
    if s.count('<')>0:
        self.rm(s)
    else:
        s=s.replace('&nbsp;', ' ')
        return s

Mais le résultat ne sera pas complet si le texte contient des symboles <> .

0
Vanjith

J'analyse les readmes de Github et je trouve que ce qui suit fonctionne vraiment bien:

import re
import lxml.html

def strip_markdown(x):
    links_sub = re.sub(r'\[(.+)\]\([^\)]+\)', r'\1', x)
    bold_sub = re.sub(r'\*\*([^*]+)\*\*', r'\1', links_sub)
    emph_sub = re.sub(r'\*([^*]+)\*', r'\1', bold_sub)
    return emph_sub

def strip_html(x):
    return lxml.html.fromstring(x).text_content() if x else ''

Et alors

readme = """<img src="https://raw.githubusercontent.com/kootenpv/sky/master/resources/skylogo.png" />

            sky is a web scraping framework, implemented with the latest python versions in mind (3.4+). 
            It uses the asynchronous `asyncio` framework, as well as many popular modules 
            and extensions.

            Most importantly, it aims for **next generation** web crawling where machine intelligence 
            is used to speed up the development/maintainance/reliability of crawling.

            It mainly does this by considering the user to be interested in content 
            from *domains*, not just a collection of *single pages*
            ([templating approach](#templating-approach))."""

strip_markdown(strip_html(readme))

Supprime tous les markdown et html correctement. 

0
PascalVKooten

hext est un package qui peut entre autres strip HTML. C'est une alternative à beautifulsoup. Ce qui suit a été testé avec hext==0.2.3.

Enregistrez ceci dans un module d’utilitaire, par exemple. util/hext.py:

import hext

_HTML_TEXT_RULE = hext.Rule('<html @text:text />')


def html_to_text(text: str) -> str:
    # Ref: https://stackoverflow.com/a/56894409/
    return _HTML_TEXT_RULE.extract(hext.Html(f'<html>{text}</html>'))[0]['text']

Exemples d'utilisation:

>>> from .util.hext import html_to_text

>>> html_to_text('<b>Hello world!</b>')
'Hello world!'

>>> html_to_text('<a href="google.com">some text</a>')
'some text'

>>> html_to_text('<span class="small-caps">l</span>-arginine minimizes immunosuppression and prothrombin time and enhances the genotoxicity of 5-fluorouracil in rats')
'l-arginine minimizes immunosuppression and prothrombin time and enhances the genotoxicity of 5-fluorouracil in rats'

>>> html_to_text('Attenuation of diabetic nephropathy by dietary fenugreek (<em>Trigonella foenum-graecum</em>) seeds and onion (<em>Allium cepa</em>) <em>via</em> suppression of glucose transporters and renin-angiotensin system')
'Attenuation of diabetic nephropathy by dietary fenugreek (Trigonella foenum-graecum) seeds and onion (Allium cepa) via suppression of glucose transporters and renin-angiotensin system'

Exemples d'utilisation avec du HTML mal formé:

>>> html_to_text('<b>Hello <i>world!')
'Hello world!'

>>> html_to_text('<a href="google.com">some <faketag>text')
'some text'
0
Acumenus

En utilisant BeautifulSoup, html2text ou le code de @Eloff, il reste la plupart du temps des éléments html, du code javascript ...

Vous pouvez donc utiliser une combinaison de ces bibliothèques et supprimer le formatage à la baisse (Python 3):

import re
import html2text
from bs4 import BeautifulSoup
def html2Text(html):
    def removeMarkdown(text):
        for current in ["^[ #*]{2,30}", "^[ ]{0,30}\d\\\.", "^[ ]{0,30}\d\."]:
            markdown = re.compile(current, flags=re.MULTILINE)
            text = markdown.sub(" ", text)
        return text
    def removeAngular(text):
        angular = re.compile("[{][|].{2,40}[|][}]|[{][*].{2,40}[*][}]|[{][{].{2,40}[}][}]|\[\[.{2,40}\]\]")
        text = angular.sub(" ", text)
        return text
    h = html2text.HTML2Text()
    h.images_to_alt = True
    h.ignore_links = True
    h.ignore_emphasis = False
    h.skip_internal_links = True
    text = h.handle(html)
    soup = BeautifulSoup(text, "html.parser")
    text = soup.text
    text = removeAngular(text)
    text = removeMarkdown(text)
    return text

Cela fonctionne bien pour moi mais cela peut être amélioré, bien sûr ...

0
hayj