Как удалить / заменить все символы между двумя точками / символами в разных подстроках [duplicate]

Это конкретный случай, но поскольку я пришел на эту страницу, ища решение и не нашел его, я добавлю его здесь.

Windows (проверена с 7) не принимать специальные символы (например, á) в именах классов и пакетов. Linux, однако.

Я узнал об этом, когда я построил .jar в NetBeans и попытался запустить его в командной строке. Он работал в NetBeans, но не в командной строке.

222
задан Peter Mortensen 20 July 2013 в 22:38
поделиться

18 ответов

Я успешно использовал ответ Eloff для Python 3.1 [большое спасибо!].

Я обновился до Python 3.2.3 и столкнулся с ошибками.

Решение, если здесь благодаря ответчику Томасу К, заключается в том, чтобы вставить super().__init__() в следующий код:

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

... чтобы он выглядел так:

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

... и он будет работать для Python 3.2.3.

Опять же, благодаря Thomas K для исправления и для Исходный код Eloff приведен выше!

363
ответ дан Community 26 August 2018 в 22:55
поделиться

Почему все вы делаете это с трудом? Вы можете использовать функцию 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)
21
ответ дан Anushka--x 26 August 2018 в 22:55
поделиться

Решение lxml.html (lxml - это родная библиотека и, следовательно, намного быстрее, чем любое чистое решение python).

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>""")
clean_tree = clean_html(tree)
print(clean_tree.text_content().strip())

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

Также см. http://lxml.de/lxmlhtml.html#cleaning-up-html , что именно делает lxml.cleaner.

Если вам нужно больше контролировать то, что именно дезинфицировано перед преобразованием в текст, вы можете явно использовать lxml Cleaner , передав опции , которые вы хотите в конструкторе, например:

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)
8
ответ дан ccpizza 26 August 2018 в 22:55
поделиться

Адаптация python 3 ответа 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 26 August 2018 в 22:55
поделиться

Вы можете использовать либо другой парсер HTML (, например lxml , либо Beautiful Soup ) - тот, который предлагает функции для извлечения только текста. Или вы можете запустить регулярное выражение в строке строки, которая удаляет теги. Подробнее см. В http://www.amk.ca/python/howto/regex/ .

2
ответ дан fish2000 26 August 2018 в 22:55
поделиться

Используя BeautifulSoup, html2text или код из @Eloff, большую часть времени он остается некоторыми элементами html, javascript-кодом ...

Таким образом, вы можете использовать комбинацию этих библиотек и удалить форматирование уценки (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

Он работает хорошо для меня, но его можно улучшить, конечно ...

0
ответ дан hayj 26 August 2018 в 22:55
поделиться

Этот метод работает безупречно для меня и не требует дополнительных установок:

import re
import htmlentitydefs

def convertentity(m):
    if m.group(1)=='#':
        try:
            return unichr(int(m.group(2)))
        except ValueError:
            return '&#%s;' % m.group(2)
        try:
            return htmlentitydefs.entitydefs[m.group(2)]
        except KeyError:
            return '&%s;' % m.group(2)

def converthtml(s):
    return re.sub(r'&(#?)(.+?);',convertentity,s)

html =  converthtml(html)
html.replace("&nbsp;", " ") ## Get rid of the remnants of certain formatting(subscript,superscript,etc).
-1
ответ дан John 26 August 2018 в 22:55
поделиться

Это быстрое исправление и может быть еще более оптимизировано, но оно будет работать нормально. Этот код заменит все непустые теги на «» и разделит все теги html на определенный входной текст. Вы можете запустить его с использованием входного входа ./file.py

    #!/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 26 August 2018 в 22:55
поделиться

Существует простой способ:

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

Идея объясняется здесь: http://youtu.be/2tu9LTDujbw

Вы может видеть, что он работает здесь: http://youtu.be/HPkNPcYed9M?t=35s

PS - Если вас интересует класс (о умной отладке с помощью python) Я даю вам ссылку: http://www.udacity.com/overview/Course/cs259/CourseRev/1 . Это бесплатно!

Добро пожаловать! :)

16
ответ дан Medeiros 26 August 2018 в 22:55
поделиться

Для одного проекта мне понадобилась стрижка HTML, а также css и js. Таким образом, я сделал вариант ответа Элоффа:

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 26 August 2018 в 22:55
поделиться

Я разбираю Github readmes, и я считаю, что следующее действительно работает хорошо:

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 ''

И затем

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))

Удаляет все отметки и html правильно.

0
ответ дан PascalVKooten 26 August 2018 в 22:55
поделиться

Вы можете написать свою собственную функцию:

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
ответ дан Peter Mortensen 26 August 2018 в 22:55
поделиться

Короткая версия!

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)

Источник регекса: MarkupSafe .

Почему я не могу просто удалить теги и оставить его?

Одно дело, чтобы люди не могли <i>italicizing</i>, не оставляя i s плавающим вокруг. Но другое - принимать произвольные данные и сделать их совершенно безвредными. Большинство методов на этой странице оставят такие вещи, как закрытые комментарии (<!--) и угловые скобки, которые не являются частью тегов (blah <<<><blah) неповрежденными. Версия HTMLParser может даже оставить полные теги, если они находятся в закрытом комментарии.

Что делать, если ваш шаблон {{ firstname }} {{ lastname }}? firstname = '<a' и lastname = 'href="http://evil.com/">' будут пропускаться каждым дескриптором тега на этой странице (кроме @Medeiros!), потому что они не являются полными тегами самостоятельно.

Версия jango strip_tags, улучшенная (см. Следующий заголовок) версия верхнего ответа на этот вопрос, дает следующее предупреждение:

Предоставляется абсолютно безотказная информация о том, что полученная строка является безопасным для HTML. Поэтому НИКОГДА не маркируйте результат вызова strip_tags, не ускоряя его, например, с помощью escape().

Следуйте их советам!

Чтобы снять метки с помощью HTMLParser, вы должны запускать его несколько раз.

Легко обойти верхний ответ на этот вопрос.

Посмотрите на эту строку ( источник и обсуждение ):

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

В первый раз, когда HTMLParser видит это, он не может сказать, что <img...> является тегом. Он выглядит сломанным, поэтому HTMLParser не избавляется от него. Он извлекает только <!-- comments -->, оставляя вас с

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

. Эта проблема была раскрыта в проекте Django в марте 2014 года. Их старый strip_tags был по существу тем же самым, что и верхний ответ на этот вопрос. Их новая версия в основном запускает ее в цикле до тех пор, пока ее запуск снова не изменит строку:

# _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

Конечно, ни одна из этих проблем не является проблемой, если вы всегда избегаете результат strip_tags().

Обновление 19 марта 2015 г. В версиях Django произошла ошибка до 1.4.20, 1.6.11, 1.7.7 и 1.8c1. Эти версии могут вводить бесконечный цикл в функцию strip_tags (). Исправленная версия воспроизводится выше. Подробнее здесь .

Хорошие вещи для копирования или использования

Мой примерный код не обрабатывает HTML-объекты - это пакеты в Django и MarkupSafe.

Мой примерный код вытащил из превосходной библиотеки MarkupSafe для предотвращения межсайтового скриптинга. Это удобно и быстро (с ускорением C к его родной версии Python). Он включен в Google App Engine и используется Jinja2 (2.7 и выше) , Mako, Pylons и т. Д. Он легко работает с шаблонами Django из Django 1.7.

Django strip_tags и другие утилиты html из последней версии хороши, но я считаю их менее удобными, чем MarkupSafe. Они довольно самодостаточны, вы можете скопировать то, что вам нужно из этого файла .

Если вам нужно удалить почти все теги, [] g8] Библиотека Bleach хороша. Вы можете заставить его применять такие правила, как «мои пользователи могут выделять курсивом, но они не могут создавать iframes».

Поймите свойства вашего стриптизера тегов! Запустите тесты Fuzz! Вот код , который я использовал для исследования этого ответа.

sheepish note - Сам вопрос касается печати на консоли, но это является лучшим результатом Google для «python strip html from string», поэтому именно этот ответ составляет 99% в Интернете.

26
ответ дан rescdsk 26 August 2018 в 22:55
поделиться

Пакет Beautiful Soup делает это немедленно для вас.

from bs4 import BeautifulSoup

soup = BeautifulSoup(html)
text = soup.get_text()
print(text)
4
ответ дан runawaykid 26 August 2018 в 22:55
поделиться

Мне нужен способ стэка тегов и декодировать объекты HTML в обычный текст. Следующее решение основано на ответе Элоффа (который я не мог использовать, потому что он разбивает сущности).

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()

Быстрый тест:

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

Результат:

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

Обработка ошибок:

  • Недопустимая структура HTML может вызвать HTMLParseError .
  • Недопустимые именованные объекты HTML (такие как &#apos;, который действителен в XML и XHTML, но не является простым HTML) приведет к исключению ValueError.
  • Числовые объекты HTML, указывающие точки кода вне диапазона Unicode, приемлемые для Python (например, на некоторых системы, символы вне Basic Multilingual Plane ) вызовут исключение ValueError.

Замечание по безопасности: не путайте HTML-удаление (преобразование HTML в обычный текст) с HTML-санированием (преобразование простого текста в HTML). Этот ответ удалит HTML и декодирует сущности в простой текст - это не делает результат безопасным для использования в контексте HTML.

Пример: &lt;script&gt;alert("Hello");&lt;/script&gt; будет преобразован в <script>alert("Hello");</script>, что на 100% правильное поведение, но, очевидно, недостаточно, если результирующий простой текст вставляется в HTML-страницу.

Правило не сложно: В любое время вы вставляете строку обычного текста в HTML вы должны всегда вывести HTML (используя cgi.escape(s, True)), даже если вы «знаете», что он не содержит HTML (например, потому что вы лишили содержимого HTML).

(Тем не менее, ОП попросил распечатать результат на консоли, и в этом случае не требуется HTML-экранирование).

26
ответ дан Søren Løvborg 26 August 2018 в 22:55
поделиться

Решения с HTML-Parser являются обрывочными, если они запускаются только один раз:

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

приводит к:

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

тому, что вы намерены предотвратить. если вы используете HTML-Parser, считайте теги до тех пор, пока не будут заменены ноль:

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
ответ дан user3232060 26 August 2018 в 22:55
поделиться

Если вы хотите удалить все теги HTML, самый простой способ, который я нашел, - использовать 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)) 

Я пробовал код принятого ответа, но получаю «RuntimeError: превышена максимальная глубина рекурсии» , что не произошло с вышеупомянутым блоком кода.

12
ответ дан Vasilis 26 August 2018 в 22:55
поделиться

Я не очень много думал о случаях, которые он пропустит, но вы можете сделать простое регулярное выражение:

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

Для тех, кто не понимает регулярное выражение, он ищет строку <...>, где внутреннее содержимое состоит из одного или нескольких (+) символов, которые не являются <. ? означает, что он будет соответствовать самой маленькой строке, которую он может найти. Например, с учетом <p>Hello</p>, он будет соответствовать <'p> и </p> отдельно с ?. Без него он будет соответствовать всей строке <..Hello..>.

Если в html (например, 2 < 3) появляется не тег <, он должен быть записан как escape-последовательность &... поэтому ^< может быть ненужным.

125
ответ дан WoJ 26 August 2018 в 22:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: