从包含在 HTML 标记和不带标记的字符串中的一系列字符串中提取文本
Posted
技术标签:
【中文标题】从包含在 HTML 标记和不带标记的字符串中的一系列字符串中提取文本【英文标题】:Extracting text from a succession of strings enclosed in HTML tags and strings without tags 【发布时间】:2020-05-13 16:30:22 【问题描述】:考虑以下 html:
<li>
<a href="url">
<b>This</b>
" is "
<b>a</b>
" test "
<b>string</b>
"!"
</a>
</li>
我想提取除"!"
之外的<a>
标签之间的所有文本。换句话说,包含在第一个开头 <b>
和最后一个结尾 </b>
之间的文本:This is a test string
。
from bs4 import BeautifulSoup
html = '''
<li>
<a href="url">
<b>This</b>
" is "
<b>a</b>
" test "
<b>string</b>
"!"
</a>
</li>
'''
soup = BeautifulSoup(html)
anchor = soup.a
请注意,<b>
标记和不带标记的字符串的数量会有所不同,因此 next
或 next_sibling
将不起作用。
有更简单的方法吗?
编辑:
理想情况下,即使在最后一个</b>
之后有多个未包含在标签中的字符串,我也想要一种有效的方法。
【问题讨论】:
可能是[c.text if isinstance(c, element.Tag) else str(c) for c in anchor.contents[:-1]]
,其中元素是from bs4 import element
@Justin Ezequiel 谢谢你的建议。这在我的示例中可行,但如果在最后一个</b>
之后有多个未包含在标签中的字符串,则可能会发生这种情况。我认为我的“尝试”示例有点令人困惑,因为它看起来好像我总是在末尾有一个字符串。
【参考方案1】:
根据您的问题和 cmets,我认为获取子字符串的索引并对 HTML 的整个子集进行操作可以满足您的需求。
让我们为retrieve all of the indexes of a substring first 创建一个函数(参见@AkiRoss 的回答):
def findall(p, s):
i = s.find(p)
while i != -1:
yield i
i = s.find(p, i+1)
然后使用它来查找<b>
和</b>
的出现。
opening_b_occurrences = [i for i in findall('<b>', html)]
# has the value of [21, 40, 58]
closing_b_occurrences = [i for i in findall('</b>', html)]
# has the value of [28, 44, 67]
现在您可以使用该信息获取 HTML 的子字符串来进行文本提取:
first_br = opening_b_occurrences[0]
last_br = closing_b_occurrences[-1] # getting the last one from list
text_inside_br = html[first_br:last_br]
text_inside_br
中的文本现在应该是 '<b>This</b>\n" is "\n<b>a</b>\n" test "\n<b>string'
。您现在可以清理它,例如通过将 </br>
附加回它并使用 BeautifulSoup 提取值或只是 using regex to do that.
【讨论】:
感谢您的建议。这也有效,但需要额外的步骤来清理输出。我认为在更复杂的情况下,它会比@Shibirraj 的答案更好,因为它混合了不同的标签类型。 @Junitar 很高兴为您提供帮助。是的,当然取决于您的用例的复杂性,如果您的与您的示例非常相似,那么 Shibirraj 的解决方案非常棒。【参考方案2】:试试下面的代码
result = ''.join([i.strip().replace('"', '') for i in anchor.strings if i.strip()][:-1])
print(result)
输出
'This is a test string'
【讨论】:
感谢您的建议。这在这种特殊情况下有效。不幸的是,如果我在最后一个</b>
之后有多个未包含在标签中的字符串,它将不起作用。
如果我没有得到任何其他答案,我会接受你的答案,因为你的答案适用于我提供的示例。也就是说,如果您知道一种无需使用特定数字切片即可处理此问题的方法,那就太好了。
@Junitar 我已经更新了答案,希望这个解决方案能解决您的问题。以上是关于从包含在 HTML 标记和不带标记的字符串中的一系列字符串中提取文本的主要内容,如果未能解决你的问题,请参考以下文章
从 Python 字符串中删除不在允许列表中的 HTML 标记
从包含 Div 和脚本标记的 html 编码字符串中动态添加 div 元素