【问题标题】:BeautifulSoup get links between stringsBeautifulSoup 获取字符串之间的链接
【发布时间】:2020-03-15 01:09:41
【问题描述】:

所以我正在使用 BS4 从网站中获取以下内容:

<div>Some TEXT with <a href="some Link">some LINK</a>
and some continuing TEXT with following <a href="some Link">some LINK</a> inside.</div>

我需要得到的是:

"Some TEXT with some LINK ("https// - actual Link") and some continuing TEXT with following some LINK ("https//- next Link") inside."

我已经为此苦苦挣扎了一段时间,不知道如何到达那里……在 [:] 之前、之后、之间、[:] 之前尝试过各种数组内传递方法来将所有东西放在一起。

我希望有人可以帮助我,因为我是 Python 新手。提前致谢。

【问题讨论】:

  • 如何在&lt;div&gt; 中搜索所有&lt;a&gt; - 即find('div').find_all('a')。之后,您应该拥有所有 &lt;a&gt; 的列表,并且您可以从列表中的每个元素中获得 get_text()["href"]

标签: python string beautifulsoup hyperlink between


【解决方案1】:

您可以使用str.joinsoup.contents 进行迭代:

import bs4
html = '''<div>Some TEXT with <a href="https// - actual Link">some LINK</a> and some continuing TEXT with following <a href="https//- next Link">some LINK</a> inside.</div>'''
result = ''.join(i if isinstance(i, bs4.element.NavigableString) else f'{i.text} ({i["href"]})' for i in bs4.BeautifulSoup(html, 'html.parser').div.contents)

输出:

'Some TEXT with some LINK (https// - actual Link) and some continuing TEXT with following some LINK (https//- next Link) inside.'

编辑:忽略br标签:

html = '''<div>Some TEXT <br> with <a href="https// - actual Link">some LINK</a> and some continuing TEXT with <br> following <a href="https//- next Link">some LINK</a> inside.</div>'''
result = ''.join(i if isinstance(i, bs4.element.NavigableString) else f'{i.text} ({i["href"]})' for i in bs4.BeautifulSoup(html, 'html.parser').div.contents \
    if getattr(i, 'name', None) != 'br')

编辑 2:递归解决方案:

def form_text(s):
  if isinstance(s, (str, bs4.element.NavigableString)):
    yield s
  elif s.name == 'a':
     yield f'{s.get_text(strip=True)} ({s["href"]})'
  else:
     for i in getattr(s, 'contents', []):
        yield from form_text(i)

html = '''<div>Some TEXT <i>other text in </i> <br> with <a href="https// - actual Link">some LINK</a> and some continuing TEXT with <br> following <a href="https//- next Link">some LINK</a> inside.</div>'''
print(' '.join(form_text(bs4.BeautifulSoup(html, 'html.parser'))))

输出:

Some TEXT  other text in     with  some LINK (https// - actual Link)  and some continuing TEXT with   following  some LINK (https//- next Link)  inside.

此外,由于br 标签等的存在,空格可能会成为问题。要解决此问题,您可以使用re.sub

import re
result = re.sub('\s+', ' ', ' '.join(form_text(bs4.BeautifulSoup(html, 'html.parser'))))

输出:

'Some TEXT other text in with some LINK (https// - actual Link) and some continuing TEXT with following some LINK (https//- next Link) inside.'

【讨论】:

  • 我正在尝试实现您的代码,因为我认为它会起作用。但是我总是遇到同样的错误: result = ''.join(i if isinstance(i, bs4.element.NavigableString), line 232, in else f'{i.text} ({i[" href"]})',第 992 行,在 getitem 中返回 self.attrs[key] KeyError: 'href'
  • @dustixx 那是因为在您运行的示例中可能存在a 以外的标签。上面的代码旨在在仅包含字符串或a 标签的示例上运行。无论哪种方式,请发布您当前使用的示例,我将编辑我的帖子。
  • 是的,我认为有时会出现的
    标签是问题所在...
  • 有没有办法忽略 html 容器中的
    标签? @Ajax1234
  • 它仍然不适合我,抱歉。我正在尝试调整您的代码,以便它适用于我,但由于我没有正确理解它,所以我不能。例如:因为我的 html 变量已经是 html = soup.find(id="ctl00_PlaceHolderMain_ctl0" -> 我不能像这样调整你的代码:result = ''.join(i if isinstance(i, bs4.element. NavigableString) else f'{i.text} ({i["href"]})' for i in html if getattr(i, 'name', None) != 'br') ->? 随着你的改变,链接不会出现在结果中,我不明白为什么......
猜你喜欢
  • 2015-06-27
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多