问题:
如何使用 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">']
尝试解决方案:
显然这在Beautifulsoup中是不可能的,这个问题:How to get the opening and closing tag in beautiful soup from HTML string?链接到 html.parser
实现自定义解析器很容易。您可以使用self.get_starttag_text()
获取与最后打开的标签对应的文本。但由于某种原因,没有类似的方法 get_endtag_text()
。
这意味着我的解析器会产生以下输出:
class MyHTMLParser(HTMLParser):
def __init__(self):
super().__init__()
self.tags = []
def reset_stored_tags(self):
self.tags = []
def handle_starttag(self, tag, attrs):
self.tags.append(self.get_starttag_text())
def handle_endtag(self, tag):
self.tags.append(self.get_endtag_text())
def handle_startendtag(self, data):
self.tags.append(self.get_starttag_text())
# input
input_doc = """<p>This <a href="book"> book </a> will help you</p>"""
parser = MyHTMLParser()
parser.feed(input_doc)
print(parser.tags)
# ['<p>', '<a href="book">', '<a href="book">', '<a href="book">']
handle_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>']
编辑:对于无效的 HTML,您可以使用 re
:
import re
html = """<p>This <a href="book"> book </a > will help you</p attr="e">"""
new_results = re.findall('\<[a-zA-Z]+.*?\>|\</[a-zA-Z]+.*?\>', html)
输出:
['<p>', '<a href="book">', '</a >', '</p attr="e">']
关于python:获取开始和结束html标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54352147/