【问题标题】:Finding the Grandchildren of a node in python bs4在python bs4中查找节点的孙子
【发布时间】:2022-01-21 06:37:49
【问题描述】:

我正在尝试从空 span 元素中的 span 元素中获取文本并在 python 中显示它们。我正在使用 bs4 并且似乎只能通过类获取 span 元素的子元素。有什么想法吗?

<span class="css-w8p71j">
    <span>
        <span>-$1.12</span>
        <span>(-0.65%)</span>
    </span>
</span>

实际的python代码

#imports
from bs4 import BeautifulSoup
import requests
from requests.api import get

#variables
link = 'HELP'
url = 'https://robinhood.com/stocks/'
runAgain = 'True'

#functions
def select():
    global link
    link = input('Input the stock ticker symbol or cmd for a list of commands: ').upper()
    print(link)
    if(link == 'HELP'):
        print('Help: use a browser to see a stocks ticker symbol, for instance AAPL for Apple. Do list in input field to see list of stock ticker symbols.')
        return
    elif(link == 'LIST'):
        print('List:\nAAPL:\tApple\nSPY:\tS&P 500 ETF\nTSLA:\tTesla\nAMC:\tAMC Entertainment\nF:\tFord Motor\nSNDL:\tSundial Growers\nMSFT:\tMicrosoft\nAMZN:\tAmazon\nDIS:\tDisney\nNIO:\tNIO')
        return
    elif(link == 'CMD'):
        print('help: gives information on how to input a stock via ticker symbol\nlist: gives a list of a few major stocks and their ticker symbol\ncmd: yields this information')
        return
    getInfo()

def getInfo():
    global link
    global url
    page = requests.get(url+link)
    if(page.status_code == 404):
        print('Stock not found or available!')
        return
    soup = BeautifulSoup(page.content, 'html.parser')
    value = soup.find("span", class_='up')
    value = (value['aria-label'])
    # change = soup.find('span', class_='css-w8p71j')

   #this is the problem area

    for item in soup.select("*[class^='css-w8p71j']"):        
        child = item.find_all("span")
        print(child) 
        # print(child[1].text)


    print('Current stock price of '+link+': '+str(value)+'\nTotal change today: ')

#main
while(runAgain == 'True'):
    select()
    runAgain = input('Would you like to run again? y/n: ').upper()
    if(runAgain == 'Y'):
        runAgain = 'True'

为背景信息添加了更多的python代码

【问题讨论】:

标签: python beautifulsoup


【解决方案1】:

注意 同意@QHarr 关于独特结构元素和属性的使用,这些绝对比动态元素和属性更可取,并且应该确定任何选择策略。

基本方法

如何将零钱价格和百分比作为一个字符串 - 通过id 选择父级&lt;div&gt;,它是第一个&lt;span&gt; 并调用.get_text() 方法:

change = soup.select_one('#sdp-price-chart-price-change span').get_text(' / ', strip=True)

Output--> -$1.12 / (-0.65%)

替代方法

使用css selectors.stripped_strings 生成器在列表中获取两个字符串分隔符。

使用select_one(),我们选择&lt;div&gt;#sdp-price-chart-price-change 中的第一个子&lt;span&gt;,其中包含两个“孙子”以及我们要查找的信息。调用 .stripped_strings 将从我们选择的每个元素中生成剥离的字符串 - 只需将其包装在 list() 中或对其进行迭代以使用结果:

change = list(soup.select_one('#sdp-price-chart-price-change span').stripped_strings)

输出为['-$1.12', '(-0.65%)'],您可以决定使用单个元素change[0]change[1],或者将它们与您喜欢的' / '.join(change) 分隔符连接到一个字符串中,...

示例

import requests
from bs4 import BeautifulSoup as bs

link = 'https://robinhood.com/stocks/AAPL'
r = requests.get(link)
soup = bs(r.content, 'lxml')

value = soup.select_one('h2 span[aria-label]')['aria-label']
change = list(soup.select_one('#sdp-price-chart-price-change span').stripped_strings)

print('Current stock price of '+link+': '+value+'\nTotal change today: '+' / '.join(change))

输出

Current stock price of https://robinhood.com/stocks/AAPL: $171.90
Total change today: -$1.12 / (-0.65%)

【讨论】:

  • 很高兴为您提供帮助,欢迎来到 Stack Overflow。如果此答案或任何其他答案解决了您的问题,请将其标记为已接受 - someone-answers - 谢谢
【解决方案2】:

避免动态查找类,使用现有的父元素 id 作为锚点,然后使用元素的关系,并通过 nth-child 过滤以定位所需的两个子节点:

import requests
from bs4 import BeautifulSoup as bs

r = requests.get('https://robinhood.com/stocks/AAPL')
soup = bs(r.content, 'lxml')
print([s.text for s in soup.select('#sdp-price-chart-price-change div:nth-child(1) span:last-child > span')]) 

阅读更多:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors

【讨论】:

    【解决方案3】:

    如果你只有一个 span 主元素,你可以使用这个:

    childs = soup.select("*[class^='css-']")[0].find_all("span")[1:]
    print(childs[0].text) 
    print(childs[1].text) 
    

    但由于情况可能并非如此,而且您很可能拥有这些元素的列表,您可以像这样对它们进行迭代:

    for item in soup.select("*[class^='css-']"):
       childs = item.find_all("span")[1:] 
       for child in childs:
           if any(str.isdigit(c) for c in child)  
               print(child.text) 
    

    【讨论】:

    • 我正在尝试从robinhood.com/stocks/AAPL 中获取零钱和百分比,您提供了一些作品,但产生了很多 []
    • 在这个链接中看不到跨度
    • 让我编辑答案
    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 2016-03-11
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    相关资源
    最近更新 更多