删除html标签并获取标记文本的开始/结束索引?

时间:2015-08-11 23:04:48

标签: python html tags markdown markup

我有一堆以降价格式的文字:

a**b**c

b c。

我已将它转换为html标签,以便更加规范:

a<strong>b</strong>c

我知道有很多工具可以转换为纯文本,但我想两者都这样做,并获得每个markdown / tag的内部文本索引。

例如,输入

a<strong>b</strong>c 

将返回剥离的文本:

abc

并给我开始(第一个字符(b)的位置)和结束(标记字符串(c)之后的第一个字符的位置),因此对于此示例(开始,结束)=(1,2)。这也必须适用于嵌套标签。我知道那里有很多库(我使用的是Python 3)来删除标签,但是我还没有找到可以完成这两项任务的库。任何人都可以通过指出这样做的东西,或描述可能有用的算法来帮助我吗?

嵌套标记示例:

某些标签可以无限地嵌套在自己的标签类型中

<sup><sup>There</sup></sup> <sup><sup>was</sup></sup> <sup><sup>another</sup></sup> <sup><sup>thread</sup></sup> <sup><sup>like</sup></sup> <sup><sup>this</sup></sup>

还列出

<ul>
<li>https://steamcommunity.com/tradeoffer/new/partner=30515749&token=WOIxg5eB</li>
<li>79</li>
<li>Why did the elephants get kicked out of the public pool?  THEY KEPT DROPPING THEIR TRUNKS! </li>
</ul>

strikethrough字体也可以嵌套在斜体等内。

<em><strike>a</strike></em>

2 个答案:

答案 0 :(得分:0)

这段代码对您来说是个不错的开始。希望它有所帮助。

import sys
from html.parser import HTMLParser

line=sys.argv[1]

class MyHTMLParser(HTMLParser):
    stripped_text = ""
    isTag = False
    isData = False
    beginDataIndices = []
    endDataIndices = []
    global_index = 0
    def handle_starttag(self, tag, attrs):
       #print("Encountered a start tag:", tag)
       self.isTag = True
    def handle_endtag(self, tag):
       #print("Encountered an end tag :", tag)
       self.isTag = False
    def handle_data(self, data):
       #print("Encountered some data  :", data)
       self.stripped_text += data
       if(self.isTag):
          self.beginDataIndices.append(self.global_index)
          self.global_index += 1
          self.isData = True
       else:
          if(self.isData):
             self.endDataIndices.append(self.global_index)
          self.isData = False
          self.global_index += 1
    def printIndices(self):
          for i in range(len(self.endDataIndices)):
             print("(%d, %d)" % (self.beginDataIndices[i], self.endDataIndices[i]))

parser = MyHTMLParser()
parser.feed(line)
print(parser.stripped_text)
parser.printIndices()

答案 1 :(得分:0)

看起来你想要的是一个HTML Parser。 HTML Parser是复杂的东西。因此,您希望使用现有库(在许多边缘情况下创建自己的库很难并且可能会失败)。不幸的是,正如this question中强调的那样,大多数现有的HTML解析库都不保留位置信息。好消息是,一个可靠地保留位置信息的HTML Parser位于Python标准库中(参见HTMLParser)。当您使用Python 3时,该解析器的问题已得到修复。

基本示例可能如下所示:

from html.parser import HTMLParser


class StripTextParser(HTMLParser):
    def __init__(self, *args, **kwargs):
        self.data = []
        super(StripTextParser, self).__init__(*args, **kwargs)

    def handle_data(self, data):
        if data.strip():
            # Only use wtrings which are contain more than whitespace
            startpos = self.getpos()
            # `self.getpos()` returns `(line, column)` of start position.
            # Use that plus length of data to calculate end position.
            endpos = (startpos[0], startpos[1] + len(data))
            self.data.append((data, startpos, endpos))


def strip_text(html):
    parser = StripTextParser()
    parser.feed(html)
    return parser.data

test1 = "<sup><sup>There</sup></sup> <sup><sup>was</sup></sup> <sup><sup>another</sup></sup> <sup><sup>thread</sup></sup> <sup><sup>like</sup></sup> <sup><sup>this</sup></sup>" 

print(strip_text(test1))

# Ouputs: [('There', (1, 10), (1, 15)), ('was', (1, 38), (1, 41)), ('another', (1, 64), (1, 71)), ('thread', (1, 94), (1, 100)), ('like', (1, 123), (1, 127)), ('this', (1, 150), (1, 154))]


test2 = """
<ul>
<li>https://steamcommunity.com/tradeoffer/new/partner=30515749&token=WOIxg5eB</li>
<li>79</li>
<li>Why did the elephants get kicked out of the public pool?  THEY KEPT DROPPING THEIR TRUNKS! </li>
</ul>
"""

print(strip_text(test2))

# Outputs: [('https://steamcommunity.com/tradeoffer/new/partner=30515749&token=WOIxg5eB', (3, 4), (3, 77)), ('79', (4, 4), (4, 6)), ('Why did the elephants get kicked out of the public pool?  THEY KEPT DROPPING THEIR TRUNKS! ', (5, 4), (5, 95))]

test3 = "<em><strike>a</strike></em>"

print(strip_text(test3))

# Outputs: [('a', (1, 12), (1, 13))]

如果没有关于输出所需格式的更具体信息,我只创建了一个元组列表。当然,您可以重构以满足您的特定需求。如果您想要所有空格,请删除if data.strip():行。