[英]python: get opening and closing html tags
題:
如何使用 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 中是不可能的,這個問題: 如何從 HTML 字符串中獲取美麗湯中的開始和結束標記? 鏈接到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">']
雖然@Ajax1234 的答案包含一些不錯的 python + beautifulsoup,但我發現它非常不穩定。 主要是因為我需要 html 標簽的確切字符串。 方法找到的每個標簽都必須出現在 html 文本中。 這會導致以下問題:
它從 HTML 解析標簽名稱和屬性,並將它們插入在一起形成標簽的字符串yield f'<{_d.name}>' if not _attrs else f'<{_d.name} {_attrs}>'
。 這消除了標簽中的多余空格: <p >
變為<p>
它總是生成一個結束標記,即使標記中沒有
對於列表屬性失敗: <p class="ab">
變為<p class="[a, b]">
空白問題可以通過在處理之前清理 HTML 來部分解決。 我用了漂白劑,但這可能太激進了。 值得注意的是,您必須在使用之前指定一個可接受的標簽列表。
更好的方法是對html.parser.HTMLParser進行瘦包裝。 這是我在我的問題中已經開始的事情,這里的區別在於我自動添加了生成結束標記。
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>']
這解決了上面提到的問題,但它有一個缺點,它不查看結束標記的實際文本。 如果結束標記中有額外的參數或空格,解析將不會顯示它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.