【问题标题】:Extracting text from multiple spans with different classes using BeautifulSoup使用 BeautifulSoup 从具有不同类的多个跨度中提取文本
【发布时间】:2020-07-22 22:16:44
【问题描述】:

我正在尝试从通过 BeautifulSoup 解析的网页中提取一些数据。

<div class="product-data-list data-points-en_GB">
<div class="float-left in-left col-totalNetAssets" style="height: 36px;">
<span class="caption">
Net Assets of Share Class
<span class="as-of-date">
as of 20-Jul-20
</span>
</span>
<span class="data">
USD 36,636,694,134
</span>
</div>
<div class="float-left in-right col-totalNetAssetsFundLevel">
<span class="caption">
Net Assets of Fund
<span class="as-of-date">
as of 20-Jul-20
</span>
</span>
<span class="data">
USD 37,992,258,237
</span>
</div>
<div class="float-left in-left col-baseCurrencyCode" style="height: 16px;">
<span class="caption">
Fund Base Currency
<span class="as-of-date">
</span>
</span>
<span class="data">
USD
</span>
</div>

我想从“caption”、“as-of-date”和“data”跨度中捕获信息,以创建如下内容: [('股份类别的净资产','20-Jul-20','USD 36,636,694,134'), ('基金净资产','20-Jul-20','USD 37,992,258,237'), ('基金基础货币','','美元')]

这是我的代码:

data=[]
for tag in soup.findAll("div", {"id": "keyFundFacts"}):
    for span in tag.findAll("div", {"class": "product-data-list data-points-en_GB"}):
        a = span.find("span", {"class": "caption"}).text
        b = span.find("span", {"class": "as-of-date"}).text
        c = span.find("span", {"class": "data"}).text
        data.append((a,b,c))

但是,当我查看“数据”列表时,我只得到 1 个结果:

<pre>
[('\nNet Assets of Share Class\n\nas of 20-Jul-20\n\n', '\nas of 20-Jul-20\n', '\nUSD 36,636,694,134\n')]
</pre>

除了需要删除新行之外,我知道我缺少一些东西来让脚本通过所有其他跨度,但我已经盯着屏幕这么久了,它并没有变得更清晰。

谁能帮我摆脱痛苦?!

【问题讨论】:

  • 因为您使用的是 span.find 而不是 span.findAll 它只返回包含您定义的类的第一个元素。

标签: python web-scraping beautifulsoup


【解决方案1】:

一种解决方案是循环浏览主要“div”下的所有 div 元素,{“class”:“product-data-list data-points-en_GB”元素。这样,对于每个 div 元素,您将获得所需的元素。

for tag in soup.findAll("div", {"id": "keyFundFacts"}):
    for element in tag.findAll("div", {"class": "product-data-list data-points-en_GB"}):
        for divEle in element.findAll('div')
            a = divEle.find("span", {"class": "caption"}).text
            b = divEle.find("span", {"class": "as-of-date"}).text
            c = divEle.find("span", {"class": "data"}).text

这会导致很多嵌套循环,所以我不推荐这样做。我建议找到更精确的方法。如果你有一个带有 html 的 url,我可以看看。

【讨论】:

  • 非常感谢您观看 Timothe。我需要使用 selenium 来获取有效负载,但我正在查看的站点在这里:blackrock.com/uk/individual/products/253743/…
  • 仅通过查看 url 上的内容结构,您似乎需要像上面一样遍历每个部分。我现在没有时间进一步研究,但如果上述解决方案不起作用,请告诉我。
  • 感谢 Timothee - 代码输出确实显示“NoneType”对象没有属性“文本”,但不用担心 - 我会继续调整它!
  • 这意味着其中一个对象可能没有特定的数据值 - 你可以实现一个简单的 try: 和 except 块来捕获任何错误并继续尝试所有其他元素
【解决方案2】:

我偶然发现了一个似乎可以解决问题的解决方案:

data=[]
for tag in soup.findAll("div", {"id": "keyFundFacts"}):
    for element in tag.findAll("div", {"class": "product-data-list data-points-en_GB"}):
        for thing in element.findChildren('div'):
            a = thing.findNext("span", {"class": "caption"}).text
            b = thing.findNext("span", {"class": "as-of-date"}).text
            c = thing.findNext("span", {"class": "data"}).text
            data.append((a,b,c))

它并不完美,但希望能发挥作用。

谢谢大家

【讨论】:

    猜你喜欢
    • 2021-10-05
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    • 2021-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多