【问题标题】:How to use Beautiful Soup to extract link under tree structure如何使用 Beautiful Soup 提取树结构下的链接
【发布时间】:2012-08-22 17:44:38
【问题描述】:

假设html网页是这样的:

<html>
    <div id="a">
        <div class="aa">
            <p>
                <a id="ff" href="#">ff</a>
                <a id="gg" href="#">gg</a>
            </p>
        </div>
        <div class="bb">
            <p>
                <a id="ff" href="#">ff</a>
            </p>
        </div>
    </div>
    <div id="b">
    </div>
</html>

使用后

soup = BeautifulSoup(webpage.read())

我有 html 网页,我想获取树结构下的链接:&lt;html&gt; -> &lt;div id="a"&gt; -> &lt;div class="aa"&gt;

如何使用 Beautiful Soup 编写以下 Python 代码?

【问题讨论】:

  • 如果您提及您到目前为止所尝试的内容,将会很有用。

标签: python beautifulsoup web-crawler


【解决方案1】:

如果没有关于您的数据的更多信息,很难为您提供涵盖所有可能输入的简洁解决方案。为了帮助您顺利上路,这里有一个演练,希望能引导您找到适合您需求的解决方案。

以下将给我们&lt;div id="a"&gt;(应该只有一个具有特定id的元素):

top_div = soup.find('div', {'id':'a'})

然后我们可以继续使用class='aa' 检索所有内部 div(可能有多个):

aa_div = top_div.findAll('div', {'class':'aa'})

从那里,我们可以返回找到的每个 div 的所有链接:

links = [div.findAll('a') for div in aa_div]

请注意,links 包含一个嵌套列表,因为div.findAll('a') 将返回找到的a 节点列表。有various ways to flatten such a list

这是一个遍历列表并打印出各个链接的示例:

>>> from itertools import chain
>>> for a in chain.from_iterable(links):
...   print a
... 
<a id="ff" href="#">ff</a>
<a id="gg" href="#">gg</a>

上面提出的解决方案相当冗长。然而,随着对输入数据的更多了解,更紧凑的解决方案是可能的。例如,如果数据与您显示的完全一样,并且始终存在divclass='aa',那么解决方案可能只是:

>>> soup.find('div', {'class':'aa'}).findAll('a')
[<a id="ff" href="#">ff</a>, <a id="gg" href="#">gg</a>]

在 BeautifulSoup4 中使用 CSS 选择器

如果您使用的是较新版本的 BeatifulSoup(版本 4),您还可以使用提供 CSS selector 支持的 .select() method。我在此答案开头提供的详尽解决方案可以重写为:

soup.select("div#a div.aa a")

对于 BeautifulSoup v3,您可以使用 soupselect 添加此功能。

但是,请注意文档中的以下声明(强调我的):

这为了解 CSS 选择器语法的用户提供了便利。您可以使用 Beautiful Soup API 完成所有这些工作。 如果你只需要 CSS 选择器,你不妨直接使用 lxml,因为它更快。但这可以让您将简单的 CSS 选择器与 Beautiful Soup API 结合起来。

【讨论】:

  • 为什么不用类 css 的选择器? soup("div#a div.aa a")
  • @Kos 我的印象是你需要像soupselect 这样的东西。 BeautifulSoup 中是否添加了 CSS 样式的选择器?如果有就太好了。
  • 是的,至少部分如此。 crummy.com/software/BeautifulSoup/bs4/doc/#css-selectors 语法为soup.select(...)
  • 谢谢。我更新了这个问题,快速提到了.select()(我相信只有BS4,在this revision中介绍过)。
【解决方案2】:

我会这样做:

from BeautifulSoup import BeautifulSoup
import urllib

url = 'http://www.website.com'
file_pointer = urllib.urlopen(url)
html_object = BeautifulSoup(file_pointer)

link_list = []
links = html_object('div',{'class':'aa'})[0]('a')
for href in links:
    link_list.append(href['href'])

这会返回一个可以通过偏移量调用的“链接”列表:

link_1 = link_list[0]
link_2 = link_list[1]

或者,如果您想要与链接关联的文本(即“单击此处”与“/Product/Store/Whatever.html”),您可以稍微更改相同的代码并产生所需的结果:

link_list = []
links = html_object('div',{'class':'aa'})[0]('a')
for text in links:
    link_list.append(text.contents[0])

同样,这将返回一个列表,因此您必须调用偏移量:

link_1_text = link_list[0]
link_2_text = link_list[1]

【讨论】:

    【解决方案3】:

    我在官方美丽的汤文档中找到了这个信息:

    for link in soup.find_all('a'):
        print(link.get('href'))
    # http://example.com/elsie
    

    你可以在这里看到更多关于美汤的信息:http://www.crummy.com/software/BeautifulSoup/bs4/doc/

    问候

    【讨论】:

      猜你喜欢
      • 2015-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-27
      • 1970-01-01
      • 2018-08-02
      • 2016-06-06
      • 2019-08-28
      相关资源
      最近更新 更多