从html删除不匹配的结束标记

时间:2019-04-08 20:05:36

标签: python html beautifulsoup

我在字符串中存储了一些html。 html无效,并且在</span>中包含不匹配的结束<td>,即

<table>
  <tr><td>
    <p>First section of text.</p>
    <p>Second section of text.</span></p>
    <table>
      <tr><td>
        <p>Third section of text.</p>
      </td></tr>
    </table>
  </td></tr>
</table>

<p>Fourth section of text.</p>

当我将html加载到BS中并使用以下方式提取为字符串时,我想使用BeautifulSoup修改html:

soup = BeautifulSoup(html, 'html.parser')
print( str( soup.prettify() ) )

BS对结构进行了重大修改。

<table>
 <tr>
  <td>
   <p>
    First section of text.
   </p>
   <p>
    Second section of text.
   </p>
  </td>
 </tr>
</table>
<table>
 <tr>
  <td>
   <p>
    Third section of text.
   </p>
  </td>
 </tr>
</table>
<p>
 Fourth section of text.
</p>

没有不匹配的</span> BS输出是我期望的

<table>
 <tr>
  <td>
   <p>
    First section of text.
   </p>
   <p>
    Second section of text.
   </p>
   <table>
    <tr>
     <td>
      <p>
       Third section of text.
      </p>
     </td>
    </tr>
   </table>
  </td>
 </tr>
</table>
<p>
 Fourth section of text.
</p>

我想做的是从html中删除不匹配的内容。如何在不编写自己的解析器寻找不匹配标签的情况下做到这一点?我希望我可以使用BS来清理代码,但这是行不通的。

2 个答案:

答案 0 :(得分:0)

您可以使用<span>将其拆分,然后加入。

from bs4 import BeautifulSoup
data='''
<table>
  <tr><td>
    <p>First section of text.</p>
    <p>Second section of text.</span></p>
    <table>
      <tr><td>
        <p>Third section of text.</p>
      </td></tr>
    </table>
  </td></tr>
</table>

<p>Fourth section of text.</p>
'''


soup=BeautifulSoup(data, 'html.parser')
data="".join(item.strip() for item in data.split("</span>"))
print(data)

这是打印输出。

<table>
  <tr><td>
    <p>First section of text.</p>
    <p>Second section of text.</p>
    <table>
      <tr><td>
        <p>Third section of text.</p>
      </td></tr>
    </table>
  </td></tr>
</table>

<p>Fourth section of text.</p>

如果您的html中存在<span>...</span>标记并希望将其从html中删除,请使用分解。

from bs4 import BeautifulSoup
data='''
<table>
  <tr><td>
    <p>First section of text.</p>
    <p>Second section of text.<span>xxxxx</span></p>
    <table>
      <tr><td>
        <p>Third section of text.</p>
      </td></tr>
    </table>
  </td></tr>
</table>

<p>Fourth section of text.</p>
'''


soup=BeautifulSoup(data, 'html.parser')

soup.span.decompose()
print(soup)

答案 1 :(得分:0)

我找到了可能的解决方案。使用html.parser来检测孤立的尾标,然后再将它们从html中删除,然后再加载到BeautifulSoup中。

from html.parser import HTMLParser

class MyHTMLParser(HTMLParser):

    def __init__(self):
        HTMLParser.__init__(self)
        self.taghash={}
        self.fixups = []

    def handle_starttag(self, tag, attrs):
        if not tag in self.taghash:
            self.taghash[tag]=1
        self.taghash[tag] = self.taghash[tag] + 1

    def handle_endtag(self, tag):
        if not tag in self.taghash:
            self.taghash[tag]=0
        self.taghash[tag] = self.taghash[tag] - 1
        if self.taghash[tag] < 0:
            print( "No unclosed starttag.", tag, self.getpos())
            self.fixups.append( (tag,self.getpos()))
    parser = MyHTMLParser()
    parser.feed(html)
    data = html.splitlines()
    parser.fixups.reverse()
    for fixup in parser.fixups:
        line = fixup[1][0]-1
        offset = fixup[1][1]
        m = re.search( "</\s*%s.?>"%fixup[0],data[line][offset:])
        data[line] = data[line][:offset]+data[line][offset+m.end():]
    html = "".join(data)