Убрать HTML из строк в Python - PullRequest
241 голосов
/ 15 апреля 2009
from mechanize import Browser
br = Browser()
br.open('http://somewebpage')
html = br.response().readlines()
for line in html:
  print line

При печати строки в файле HTML я пытаюсь найти способ показать только содержимое каждого элемента HTML, а не само форматирование. Если он найдет '<a href="whatever.com">some text</a>', он напечатает только «некоторый текст», '<b>hello</b>' напечатает «привет» и т. Д. Как можно поступить так?

Ответы [ 23 ]

2 голосов
/ 15 апреля 2009

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

1 голос
/ 07 августа 2015

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

    #!/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 голос
/ 18 июня 2012

Я успешно использовал ответ Элоффа для 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.

Еще раз, спасибо Томасу К за исправление и за оригинальный код Элоффа, предоставленный выше!

1 голос
/ 24 января 2014

Все решения с HTML-парсером можно взломать, если они запускаются только один раз:

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

Результат:

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

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

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 голос
/ 15 января 2018

Для одного проекта мне нужно было раздеть HTML, а также CSS и JS. Таким образом, я сделал вариант ответа Eloffs:

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 голос
/ 19 октября 2018

Вот решение, аналогичное принятому в настоящее время ответу (https://stackoverflow.com/a/925630/95989),, за исключением того, что оно использует внутренний класс HTMLParser напрямую (т.е. без подклассов), что делает его значительно более кратким:

def strip_html(text):
    parts = []                                                                      
    parser = HTMLParser()                                                           
    parser.handle_data = parts.append                                               
    parser.feed(text)                                                               
    return ''.join(parts)
1 голос
/ 16 мая 2017

Адаптация ответа Сёрена-Левборга на Python 3

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()
0 голосов
/ 08 апреля 2019

Простой код !. Это удалит все виды тегов и содержимого внутри него.

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

Но это не даст полного результата, если текст содержит <> символов внутри него.

0 голосов
/ 18 февраля 2019

Вот мое решение для 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

Не уверен, что это идеально, но решил мой вариант использования и кажется простым.

0 голосов
/ 27 декабря 2017

Используя 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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...