簡體   English   中英

python:獲取打開和關閉html標簽

[英]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_endtagtag參數只是一個字符串"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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM