python:获取开始和结束html标记

python:获取开始和结束html标记,python,html,python-3.x,beautifulsoup,html-parsing,Python,Html,Python 3.x,Beautifulsoup,Html Parsing,问题: 如何使用python(3.6)查找所有打开和关闭HTML标记的文本。 这需要是精确的文本,保留空格和可能非法的html: # input html = """<p>This <a href="book"> book </a > will help you</p attr="e">""" # desired output output = ['<p>', '<a href="book">', '</a &g

问题:

如何使用python(3.6)查找所有打开和关闭HTML标记的文本。 这需要是精确的文本,保留空格和可能非法的html:

# input
html = """<p>This <a href="book"> book </a  > will help you</p attr="e">"""

# desired output
output = ['<p>', '<a href="book">', '</a  >', '</p attr="e">']

handle\u endtag
tag
参数只是一个字符串
“a”
“p”
,而不是一些可以提供整个标记的自定义数据类型。

您可以使用递归并迭代
soup。contents
属性:

from bs4 import BeautifulSoup as soup

html = """<p>This <a href="book"> book </a> will help you</p>"""

def attrs(_d):
  if _d.name != '[document]':
    _attrs = ' '.join(f'{a}="{b}"' for a, b in getattr(_d, 'attrs', {}).items())
    yield f'<{_d.name}>' if not _attrs else f'<{_d.name} {_attrs}>'
  for i in _d.contents:
    if not isinstance(i, str):
       yield from attrs(i)
  if _d.name != '[document]':
    yield f'</{_d.name}>'

print(list(attrs(soup(html, 'html.parser'))))
输出:

['<p>', '<a href="book">', '</a>', '</p>']
['<p>', '<a href="book">', '</a  >', '</p attr="e">']
['','','

']
虽然@Ajax1234的答案包含一些不错的python+beautifulsoup,但我发现它非常不稳定。主要是因为我需要html标记的确切字符串该方法找到的每个标记必须出现在html文本中。这会导致以下问题:

  • 它解析HTML中的标记名和属性并插入它们 一起构成标记的字符串
    如果没有,则产生f'.\u attrs else f'.
    。这样就消除了标记中多余的空白:
    变成了

  • 它总是生成结束标记,即使标记中没有结束标记

  • 它对于列表属性失败:

    变成

通过在处理HTML之前清除HTML,可以部分解决空白问题。我用过,但那可能太激进了。值得注意的是,在使用之前,您必须指定一个已接受标记的列表

一个更好的方法是用薄薄的包装。 这是我在我的问题中已经开始的,这里的区别是我自动添加并生成一个结束标记

from html.parser import HTMLParser

class MyHTMLParser(HTMLParser):
    def __init__(self):
        super().__init__()
        self.tags = []

    def handle_starttag(self, tag, attrs):
        self.tags.append(self.get_starttag_text())

    def handle_endtag(self, tag):
        self.tags.append(f"</{tag}>")

parser = MyHTMLParser();
parser.feed("""<p > Argh, whitespace and p is not closed </a>""")
parser.tags # ['<p >', '</a>']
从html.parser导入HTMLParser
类MyHtmlPasser(HtmlPasser):
定义初始化(自):
super()。\uuuu init\uuuuu()
self.tags=[]
def句柄\u开始标记(自身、标记、属性):
self.tags.append(self.get\u starttag\u text())
def handle_endtag(self,tag):
self.tags.append(f“”)
parser=MyHTMLParser();
feed(“Argh,空格和p未关闭”)
parser.tags#['',']

这解决了上面提到的问题,但它有一个缺点,它没有查看结束标记的实际文本。如果结束标记中有额外的参数或空格,解析将不会显示它们。

您使用的是什么Python版本?@DanielMesejo version 3.6oh lala,fancy:D不幸的是,我需要标记的确切文本。例如“

”应该保留这两个空格。@lhk HTML数据的来源和用途是什么?我不确定这可以在
bs4
中轻松实现。您可能需要使用正则表达式,我希望获取HTML中包含的文本,通过语言处理管道运行它,更改部分内容,并将更改后的文本插入HTML标记中。为此,我需要删除HTML标记并将它们重新插入。如果我知道标记的确切文本,我可以用“THISISHTML”之类的东西替换所有标记,然后用spacy标记它,删除“THISISHTML”标记,但保留它们的索引。在处理之后,在每个索引处,我将html标记添加回。但这意味着正确识别标签。我有一个正则表达式解决方案,但是它有问题,所以我想从一个健壮的html解析器获得html标记,而不是正则表达式。令人惊讶的是,我还没有找到一个可以轻松做到这一点的框架。Beautifulsoup只提供所有标记及其内容,漂白剂可以删除标记,但不会告诉您它删除了什么,html.parser有一个奇怪的缺少get_end_标记的方法,……我想我找到了一个很好的方法:用漂白剂清理html,然后使用代码。但漂白剂似乎很不一致。
['<p>', '<a href="book">', '</a  >', '</p attr="e">']
from html.parser import HTMLParser

class MyHTMLParser(HTMLParser):
    def __init__(self):
        super().__init__()
        self.tags = []

    def handle_starttag(self, tag, attrs):
        self.tags.append(self.get_starttag_text())

    def handle_endtag(self, tag):
        self.tags.append(f"</{tag}>")

parser = MyHTMLParser();
parser.feed("""<p > Argh, whitespace and p is not closed </a>""")
parser.tags # ['<p >', '</a>']