我正在尝试使用Beautifuloup来提取html标签并删除文本。例如,拿这个html:
html_page = """
<html>
<body>
<table>
<tr class=tb1><td>Lorem Ipsum dolor Sit amet</td></tr>
<tr class=tb1><td>Consectetuer adipiscing elit</td></tr>
<tr><td>Aliquam Tincidunt mauris eu Risus</td></tr>
<tr><td>Vestibulum Auctor Dapibus neque</td></tr>
</table>
</body>
</html>
"""
期望的结果是:
<html>
<body>
<table>
<tr><td></td></tr>
<tr><td></td></tr>
<tr><td></td></tr>
<tr><td></td></tr>
</table>
</body>
</html>
这是我到目前为止所得到的:
def get_tags(soup):
copy_soup = soup
for tag in copy_soup.findAll(True):
tag.attrs = {} # removes attributes of a tag
tag.string = ''
return copy_soup
print get_tags(soup)
使用tag.attrs = {}可以删除所有标记属性。但是当我尝试使用tag.string或tag.clear()时,我只剩下<html></html>
。我理解可能发生的事情是在使用tag.string
或tag.clear()
的第一次迭代中删除html标记内的所有内容。
我不确定如何解决这个问题。也许先递归删除孩子的文字?或者,我缺少一种更简单的方法吗?
答案 0 :(得分:1)
您不能简单地将.string
重置为空字符串,因为如果某个元素有一个包含文本的子项,例如示例中的tr
元素,则会无意中删除td
个元素从树上。
您不能使用.clear()
,因为它也会递归删除所有子节点。
我不记得在没有BeautifulSoup
数据的情况下获取HTML树结构的内置方法 - 我使用以下方法:
for elm in soup.find_all():
if not elm.find(recursive=False): # if not children
elm.string = ''
elm.attrs = {}
我们只在没有孩子的情况下重置.string
。
演示:
>>> from bs4 import BeautifulSoup
>>>
>>> html_page = """
... <html>
... <body>
... <table>
... <tr class=tb1><td>Lorem Ipsum dolor Sit amet</td></tr>
... <tr class=tb1><td>Consectetuer adipiscing elit</td></tr>
... <tr><td>Aliquam Tincidunt mauris eu Risus</td></tr>
... <tr><td>Vestibulum Auctor Dapibus neque</td></tr>
... </table>
... </body>
... </html>
... """
>>>
>>> soup = BeautifulSoup(html_page, "html.parser")
>>> for elm in soup.find_all():
... if not elm.find(recursive=False):
... elm.string = ''
... elm.attrs = {}
...
>>> print(soup.prettify())
<html>
<body>
<table>
<tr>
<td>
</td>
</tr>
<tr>
<td>
</td>
</tr>
<tr>
<td>
</td>
</tr>
<tr>
<td>
</td>
</tr>
</table>
</body>
</html>
答案 1 :(得分:1)
实际上,我能够通过递归更新子标签来删除文本。您还可以在递归中更新其属性。
from bs4 import BeautifulSoup
from bs4.element import NavigableString
def delete_displayed_text(element):
"""
delete displayed text from beautiful soup tag element object recursively
:param element: beautiful soup tag element object
:return: beautiful soup tag element object
"""
new_children = []
for child in element.contents:
if not isinstance(child, NavigableString):
new_children.append(delete_displayed_text(child))
element.contents = new_children
return element
if __name__ =='__main__':
html_code_sample = '<div class="hello">I am not supposed to be displayed<a>me neither</a></div>'
soup = BeautifulSoup(html_code_sample, 'html.parser')
soup = delete_displayed_text(soup)
cleaned_soup = BeautifulSoup(str(soup), 'html.parser')
print(cleaned_soup.getText())