Beautifulsoup删除重复的父母和子标记

时间:2018-01-08 16:46:40

标签: python html beautifulsoup

我正在尝试删除BeautifulSoup输出中包含文本的重复标记。

scrape_selected_tags是BeautifulSoup类型bs4.element.ResultSet,输出:

[<img/>]
[<img/> <a>1</a> <a>1</a> <a><b>1</b></a> <a><b>1</b><c>3</c></a> <img/>]

我尝试删除重复项:

check_list = []

for i in scrape_selected_tags:
    if i not in check_list:
        check_list.append(i)
    else:
        "".join(re.findall("<\w+>|</\w+>|<\w+/>", str(i)))

print check_list

输出:

[<img/>]
[<img/>, <a>1</a>, <a><b>1</b></a>, <a><b>1</b><c>3</c></a>]

<a>1</a>中的第二个元素中删除重复的<img>scrape_selected_tags。但是,我想保留<img>标记,因为它不包含文字,我希望保留标记<a></a>以展示原来<a>1</a>,即输出:

[<img/>]
[<img/>, <a>1</a>, <a></a>, <a><b>1</b></a>, <a><b>1</b><c>3</c></a>, <img/>]

如何修改我的代码才能执行此操作?

我也想将这个应用于重复的子标签。我的最终所需输出如下,其中<b>1</b>从最后一个元素中删除,但<b></b>标记仍然存在。

[<img/>]
[<img/>, <a>1</a>, <a></a>, <a><b>1</b></a>, <a><b></b><c>3</c></a>, <img/>]

我尝试使用新的for循环遍历check_list

for i in [child for parent in check_list for child in parent.find_all()]:
    print i

这将检索所有子标记。使用与父标记相同的方法删除它们不起作用。我不能使用set函数,因为我想保留不包含字符串的标记,例如<img>。这就是我使用正则表达式的原因。

提前谢谢你。

1 个答案:

答案 0 :(得分:1)

关于问题的第一部分,如果列表中包含Tag.name字符串,您可以使用标记名称列表来保留和查找。
对于重复标记,您可以创建没有文本内容的新Tag对象。

from bs4 import BeautifulSoup, Tag

scrape_selected_tags = ['<img/>', '<a>1</a>', '<a>1</a>', '<a><b>1</b></a>', '<a><b>1</b><c>3</c></a>', '<img/>']
scrape_selected_tags = [BeautifulSoup(tag, 'html.parser').find() for tag in scrape_selected_tags]

keep = ['img']
check_list = []

for i in scrape_selected_tags:
    if i not in check_list or i.name in keep:
        check_list.append(i)
    else:
        check_list.append(Tag(name=i.name))

print check_list
  

[<img/>, <a>1</a>, <a></a>, <a><b>1</b></a>, <a><b>1</b><c>3</c></a>, <img/>]

将这些规则应用于嵌套标记有点困难。您必须展平check_list中的项目,以检查嵌套在新项目中的任何标记是否包含在列表中已有的任何标记中。

如果是,请创建一个新的空Tag并使用replace_with方法替换旧标记,然后再将该项添加到列表中。

for i in scrape_selected_tags:
    tag = i if i not in check_list or i.name in keep else Tag(name=i.name)
    for child in tag.find_all():
        if child in [ct for pt in check_list for ct in [pt] + pt.find_all()]:
            child.replace_with(Tag(name=child.name))
    check_list.append(tag)

print check_list
  

[<img/>, <a>1</a>, <a></a>, <a><b>1</b></a>, <a><b></b><c>3</c></a>, <img/>]