如何使用 BeautifulSoup4 获取 <br> 标签之前的所有文本

Posted

技术标签:

【中文标题】如何使用 BeautifulSoup4 获取 <br> 标签之前的所有文本【英文标题】:How do I use BeautifulSoup4 to get ALL text before <br> tag 【发布时间】:2018-07-21 05:05:20 【问题描述】:

我正在尝试为我的应用抓取一些数据。我的问题是我需要一些 这是 html 代码:

<tr>
  <td>
    This
    <a class="tip info" href="blablablablabla">is a first</a>
    sentence.
    <br>
    This
    <a class="tip info" href="blablablablabla">is a second</a>
    sentence.
    <br>This
    <a class="tip info" href="blablablablabla">is a third</a>
    sentence.
    <br>
  </td>
</tr>

我希望输出看起来像

这是第一句话。 这是第二句话。 这是第三句话。

有可能吗?

【问题讨论】:

您尝试过以下解决方案吗?人们正在尝试解决您的问题,但您甚至不关心回复@user4937980! 抱歉,我刚醒了几个小时。最后我使用了SIM的方法,它就像一个老板一样工作。以下所有解决方案都很棒。顺便说一句,网络爬虫真的很难学:'( 【参考方案1】:

试试这个。它应该为您提供所需的输出。只需将以下脚本中使用的content 变量视为您上面粘贴的html elements 的持有者。

from bs4 import BeautifulSoup

soup = BeautifulSoup(content,"lxml")
items = ','.join([''.join([item.previous_sibling,item.text,item.next_sibling]) for item in soup.select(".tip.info")])
data = ' '.join(items.split()).replace(",","\n")
print(data)

输出:

This is a first sentence. 
This is a second sentence. 
This is a third sentence.

【讨论】:

【参考方案2】:

这当然是可能的。我会稍微笼统地回答,因为我怀疑您是否只想处理那段 HTML。

首先,获取指向td元素的指针,

td = soup.find('td')

现在,请注意,您可以获得此元素的子元素的列表,

>>> td_kids = list(td.children)
>>> td_kids
['\n    This\n    ', <a class="tip info" href="blablablablabla">is a first</a>, '\n    sentence.\n    ', <br/>, '\n    This\n    ', <a class="tip info" href="blablablablabla">is a second</a>, '\n    sentence.\n    ', <br/>, 'This\n    ', <a class="tip info" href="blablablablabla">is a third</a>, '\n    sentence.\n    ', <br/>, '\n']

此列表中的一些项目是字符串,一些是 HTML 元素。至关重要的是,有些是 br 元素。

您可以首先通过查找将列表拆分为一个或多个列表,

isinstance(td_kid[<some k>], bs4.element.Tag)

对于列表中的每个项目。

然后,您可以遍历每个子列表,通过将它们变成汤来重复替换标签,然后获取这些子列表的子列表。最终,您将拥有几个子列表,其中仅包含 BeautifulSoup 所谓的“可导航字符串”,您可以照常操作。

将元素连接在一起,然后我建议您使用正则表达式 sub 消除空格,如下所示:

result = re.sub(r'\s2,', '', <joined list>)

【讨论】:

【参考方案3】:

您可以使用bs4 和基本的字符串操作轻松做到这一点,如下所示:

from bs4 import BeautifulSoup

data = '''
<tr>
  <td>
    This
    <a class="tip info" href="blablablablabla">is a first</a>
    sentence.
    <br>
    This
    <a class="tip info" href="blablablablabla">is a second</a>
    sentence.
    <br>This
    <a class="tip info" href="blablablablabla">is a third</a>
    sentence.
    <br>
  </td>
</tr>
'''

soup = BeautifulSoup(data, 'html.parser')
for i in soup.find_all('td'):
    print ' '.join(i.text.split()).replace('. ', '.\n')

这将作为输出:

This is a first sentence.
This is a second sentence.
This is a third sentence.

【讨论】:

@novice-coder 是的,我知道 - 但是网络抓取很大程度上取决于内容格式(在这种情况下,OP 想要完整的句子 - 因此是点)。无论如何,这可以由 OP 根据实际内容轻松修复。这个答案中重要的是i.text,因为许多程序员往往会忘记或忽略它甚至存在!【参考方案4】:
htmlText = """<tr>
  <td>
    This
    <a class="tip info" href="blablablablabla">is a first</a>
    sentence.
    <br>
    This
    <a class="tip info" href="blablablablabla">is a second</a>
    sentence.
    <br>This
    <a class="tip info" href="blablablablabla">is a third</a>
    sentence.
    <br>
  </td>
</tr>"""
from bs4 import BeautifulSoup
# these two steps are to put everything into one line. may not be necessary for you
htmlText = htmlText.replace("\n", " ")
while "  " in htmlText:
    htmlText = htmlText.replace("  ", " ")

# import into bs4
soup = BeautifulSoup(htmlText, "lxml")

# using https://***.com/a/34640357/5702157
for br in soup.find_all("br"):
    br.replace_with("\n")

parsedText = soup.get_text()
while "\n " in parsedText:
    parsedText = parsedText.replace("\n ", "\n") # remove spaces at the start of new lines
print(parsedText.strip())

【讨论】:

以上是关于如何使用 BeautifulSoup4 获取 <br> 标签之前的所有文本的主要内容,如果未能解决你的问题,请参考以下文章

Beautifulsoup4 没有返回页面上的所有链接

如何从 BeautifulSoup4 中的 html 标签中找到特定的数据属性?

如何使用python和beautifulsoup4循环抓取网站中多个页面的数据

使用python和beautifulsoup4抓取网页后重复数据

Python利用BeautifulSoup4库获取input标签的value值

python BeautifulSoup4 获取 script 节点问题