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.findall
and之间存在有意义的区别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)