我必须将一个文档的一部分复制到另一个文档,但是我不想修改 从中复制的文档。
如果使用.extract()它,则从树中删除该元素。如果我只是追加 选定的元素,document2.append(document1.tag)它仍然会 从document1中删除该元素。
.extract()
document2.append(document1.tag)
当我使用真实文件时,修改后我不能保存document1,但是 有什么方法可以做到不破坏文档?
在4.4版 (2015年7月发布)之前的BeautifulSoup中没有本地克隆功能。您必须自己创建一个深层副本,这很 棘手,因为每个元素都维护着到树的其余部分的链接。
要克隆一个元素及其所有元素,您必须复制所有属性 并重置其父子关系。这必须递归地进行。 最好通过不复制关系属性并重新安置每个 递归克隆的元素来做到这一点:
from bs4 import Tag, NavigableString def clone(el): if isinstance(el, NavigableString): return type(el)(el) copy = Tag(None, el.builder, el.name, el.namespace, el.nsprefix) # work around bug where there is no builder set # https://bugs.launchpad.net/beautifulsoup/+bug/1307471 copy.attrs = dict(el.attrs) for attr in ('can_be_empty_element', 'hidden'): setattr(copy, attr, getattr(el, attr)) for child in el.contents: copy.append(clone(child)) return copy
该方法对当前的BeautifulSoup版本敏感。我 使用4.3进行了测试,将来的版本可能还会添加需要 复制的属性。
您也可以将此功能猴子修补到BeautifulSoup中:
from bs4 import Tag, NavigableString def tag_clone(self): copy = type(self)(None, self.builder, self.name, self.namespace, self.nsprefix) # work around bug where there is no builder set # https://bugs.launchpad.net/beautifulsoup/+bug/1307471 copy.attrs = dict(self.attrs) for attr in ('can_be_empty_element', 'hidden'): setattr(copy, attr, getattr(self, attr)) for child in self.contents: copy.append(child.clone()) return copy Tag.clone = tag_clone NavigableString.clone = lambda self: type(self)(self)
让您.clone()直接调用元素:
.clone()
document2.body.append(document1.find('div', id_='someid').clone())
我的功能要求,以对BeautifulSoup项目被接受,并 调整了使用copy.copy()功能; 现在, BeautifulSoup 4.4已发布,您可以使用该版本(或更高版本)并执行以下操作:
import copy document2.body.append(copy.copy(document1.find('div', id_='someid')))