unwrap() 之后使用 beautifulSoup 获取真实文本

Que*_*tin 2 python beautifulsoup

我需要你的帮助:我有<p>带有许多其他标签的标签,如下例所示:

<p>I <strong>AM</strong> a <i>text</i>.</p>
Run Code Online (Sandbox Code Playgroud)

我只想得到“我是文本”,所以我 unwrap() 标签strongi 使用下面的代码:

for elem in soup.find_all(['strong', 'i']):
    elem.unwrap()
Run Code Online (Sandbox Code Playgroud)

接下来,如果我打印一切soup.p都正确,但如果我不知道我的字符串所在的标签的名称,问题就会开始!

下面的代码应该更清楚:

from bs4 import BeautifulSoup

html = '''
<html>
    <header></header>
    <body>
        <p>I <strong>AM</strong> a <i>text</i>.</p>
    </body>
</html>
'''
soup = BeautifulSoup(html, 'lxml')

for elem in soup.find_all(['strong', 'i']):
    elem.unwrap()

print soup.p 
# output :
# <p>I AM a text.</p>

for s in soup.stripped_strings:
    print s
# output 

'''
I
AM
a
text
.
'''
Run Code Online (Sandbox Code Playgroud)

为什么 BeautifulSoup 将我的所有字符串分开,而我之前将它与我的 unwrap() 连接起来?

Wil*_*sem 6

如果您使用.unwrap()标签,则删除该标签,并将内容放入父标签中。但是文本没有合并,因此,您获得了s的列表NavigableString( 的子类str):

>>> [(c,type(c)) for c in soup.p.children]
[('I ', <class 'bs4.element.NavigableString'>), ('AM', <class 'bs4.element.NavigableString'>), (' a ', <class 'bs4.element.NavigableString'>), ('text', <class 'bs4.element.NavigableString'>), ('.', <class 'bs4.element.NavigableString'>)]
Run Code Online (Sandbox Code Playgroud)

因此,这些元素中的每一个都是一个单独的文本元素。因此,尽管您删除了标签本身并注入了文本,但这些字符串并未连接起来。这似乎是合乎逻辑的,因为左侧和右侧的元素仍然可以是标签:通过展开,<strong>您并没有<i>同时展开。

但是,您可以使用.text, 来获取全文:

>>> soup.p.get_text()
'I AM a text.'
Run Code Online (Sandbox Code Playgroud)

或者您可以决定将join这些元素放在一起:

>>> ''.join(soup.p.strings)
'I AM a text.'
Run Code Online (Sandbox Code Playgroud)

  • @Quentin您可以通过检查展开元素的开头和结尾以及之前和之后的“NavigableString”来“随时随地”连接它,并用合适的连接的“NavigableString”替换它们。不过,API 中没有内置任何内容。 (2认同)