ET.findall()与BS4.find_all():
findall()默认情况下,ElementTree不是递归的*。它只会找到提供的节点的直接子节点。因此,在您的情况下,它仅在根元素下直接搜索图像节点。
- BeautifulSoup
find_all() 搜索所有后代。因此它会在树中的任何位置搜索“imagedata”节点。
但是,ElementTree.iter()确实搜索所有后代。使用文档中的“使用命名空间”示例:
>>> for char in root.iter('{http://characters.example.com}character'):
... print(' |-->', char.text)
...
|--> Lancelot
|--> Archie Leach
|--> Sir Robin
|--> Gunther
|--> Commander Clement
- 可悲的是,
ET.iterfind()它使用命名空间作为 dict(如 ET.findall),也不会搜索 descendants ,默认情况下只搜索直接子代*。就像 ET.findall。除了''标签中的空字符串如何在命名空间中被处理,一个返回一个列表而另一个返回一个迭代器,我不能说ET.findalland之间存在有意义的区别ET.iterfind。
- *如上
ET.findall(),前缀".//"使其搜索整个树(与任何节点匹配)。
当您使用带有 ET 的名称空间时,您仍然需要带有标签的名称空间名称。结果行应该是:
namespace = {'v': "urn:schemas-microsoft-com:vml"}
results = ET.fromstring(xml).findall("v:imagedata", namespace) # note the 'v:'
此外,'v'不需要是 a 'v',如果需要,您可以将其更改为更有意义的内容:
namespace = {'image': "urn:schemas-microsoft-com:vml"}
results = ET.fromstring(xml).findall("image:imagedata", namespace)
当然,如果它们不是根的直接子元素,这仍然不一定会为您提供所有 imagedata 元素。为此,您需要创建一个递归函数来为您执行此操作。有关如何查看此答案的信息。请注意,虽然该答案进行递归搜索,但如果后代深度太深,您可能会达到 Python 的递归限制。
要获取树中任意位置的所有 imagedata 元素,请使用".//"前缀:
results = ET.fromstring(xml).findall(".//v:imagedata", namespace)