Python 获取具有任意嵌套度的html元素的内容(以及内容的xpath)
我正在寻找一种方法来读取任意嵌套程度的HTML元素的文本内容(即没有HTML代码) 如果没有嵌套,那就很容易了,但由于HTML不是一种常规语言 可以用漂亮的汤来做这个吗?比如:Python 获取具有任意嵌套度的html元素的内容(以及内容的xpath),python,html,parsing,xpath,beautifulsoup,Python,Html,Parsing,Xpath,Beautifulsoup,我正在寻找一种方法来读取任意嵌套程度的HTML元素的文本内容(即没有HTML代码) 如果没有嵌套,那就很容易了,但由于HTML不是一种常规语言 可以用漂亮的汤来做这个吗?比如: page = soup.find('*').getText() # obviously this won't give xpath info ('text of div 1', '/div'), ('text of span 1', '/div/span'), ('text of span 2', '/div/spa
page = soup.find('*').getText() # obviously this won't give xpath info
('text of div 1', '/div'), ('text of span 1', '/div/span'), ('text of span 2', '/div/span/span')
我可以想象使用生成器将不同的标记名输入到find
函数中,但我不知道标记名是什么。我还需要返回一些类似于xpath的内容引用,以便我知道最终从find
函数返回的内容的来源
因此,对于以下HTML:
<div>
text of div 1
<span>
text of span 1
<span>
text of span 2
</span>
</span>
</div>
那么这个呢:
result_set = []
for tag in soup.find_all():
parent_list = []
content_of_tag = tag.find(text=True)
parent_list.append(tag.name)
while tag.parent is not None:
tag = tag.parent
parent_list.append(tag.name)
result_set.append((content_of_tag, parent_list))
第一个
find_all()
将查找所有级别上所有类型的所有标记。迭代这些tag.find(text=True)
查找每个标记中的第一个文本parent\u list.append(tag.name)
在循环将当前标记名称添加到父列表之前。然后,while循环查找所有标记的父项,并将它们的名称添加到父项列表中。我编写了一个递归函数,该函数将返回字典中标记中所有文本的XPath,格式如下:
{'xpath1': {'text': 'text1'}, 'xpath2': {'text': 'text2'}, ...}
代码:
我知道这不是您期望的输出格式。但是,您可以将其转换为您想要的任何格式。例如,要将其转换为预期输出,只需执行以下操作:
expected_output = [(v['text'], k) for k, v in xpaths.items()]
print(expected_output)
输出:
{'/div': {'text': 'text of div 1', 'count': 1}, '/div/span': {'text': 'text of span 1.1', 'count': 1}, '/div/span/span': {'text': 'text of span 2.1', 'count': 2}, '/div/span/span[2]': {'text': 'text of span 2.2'}, '/div/span/span[2]/span': {'text': 'text of span 3', 'count': 1}}
[('text of div 1', '/div'), ('text of span 1.1', '/div/span'), ('text of span 2.1', '/div/span/span'), ('text of span 2.2', '/div/span/span[2]'), ('text of span 3', '/div/span/span[2]/span')]
一些解释:
字典中的额外键count
用于存储当前标记中具有相同名称的标记数。使用这种格式(字典)可以大大优化代码。您将只访问每个标签一次
奖金:
由于该函数返回一个以XPATH为键的字典,因此可以使用XPATH获取任何文本。例如:
xpaths = get_xpaths_dict(soup.div)
print(xpaths['/div/span/span[2]/span']['text'])
# text of span 3
这种逻辑对我来说是有意义的,但是如果在同一级别上有多个具有相同名称的标记,那么父列表不会产生非唯一标识符吗?例如
12
@DavidJ。是的,对于具有相同父级的同一级别的标记,父级列表将是非唯一的。我真的想不出一个好的解决方案,但如果你想,请分享你的解决方案。很好的答案,这正是我想要的。
xpaths = get_xpaths_dict(soup.div)
print(xpaths['/div/span/span[2]/span']['text'])
# text of span 3