如何使用Beautiful Soup从复杂的div类中抓取内容



我正在做一些练习,用Python练习网络抓取,我想得到这个雅虎页面(纽约证券交易所美国银行)表格的第一行("总收入")的值。

查看页面源代码,我的想法是找到第一个出现的<div class="" data-test="fin-row">并获取值,但我不确定如何在第一个div中导航

下面我展示了第一行显示的HTML代码:

<div class="" data-test="fin-row">
<div class="D(tbr) fi-row Bgc($hoverBgColor):h">
<div class="D(tbc) Ta(start) Pend(15px)--mv2 Pend(10px) Bxz(bb) Py(8px) Bdends(s) Bdbs(s) Bdstarts(s) Bdstartw(1px) Bdbw(1px) Bdendw(1px) Bdc($seperatorColor) Pos(st) Start(0) Bgc($lv2BgColor) fi-row:h_Bgc($hoverBgColor) Pstart(15px)--mv2 Pstart(10px)">
<div class="D(ib) Va(m) Ell Mt(-3px) W(215px)--mv2 W(200px) undefined" title="Total Revenue">
<button aria-label="Total Revenue" class="P(0) M(0) Va(m) Bd(0) Fz(s) Mend(2px) tgglBtn">
<svg class="H(16px) Fill($primaryColor) Stk($primaryColor) tgglBtn:h_Fill($linkColor) tgglBtn:h_Stk($linkColor) Cur(p)" width="16" style="stroke-width:0;vertical-align:bottom" height="16" viewBox="0 0 48 48" data-icon="caret-right">
<path d="M33.447 24.102L20.72 11.375c-.78-.78-2.048-.78-2.828 0-.78.78-.78 2.047 0 2.828l9.9 9.9-9.9 9.9c-.78.78-.78 2.047 0 2.827.78.78 2.047.78 2.828 0l12.727-12.728z"></path>
</svg>
</button>
<span class="Va(m)">Total Revenue</span>
</div>
<div class="W(3px) Pos(a) Start(100%) T(0) H(100%) Bg($pfColumnFakeShadowGradient) Pe(n) Pend(5px)"></div>
</div>
<div class="Ta(c) Py(6px) Bxz(bb) BdB Bdc($seperatorColor) Miw(120px) Miw(100px)--pnclg Bgc($lv1BgColor) fi-row:h_Bgc($hoverBgColor) D(tbc)" data-test="fin-col"><span>90,742,000</span></div>
<div class="Ta(c) Py(6px) Bxz(bb) BdB Bdc($seperatorColor) Miw(120px) Miw(100px)--pnclg D(tbc)" data-test="fin-col"><span>89,113,000</span></div>
<div class="Ta(c) Py(6px) Bxz(bb) BdB Bdc($seperatorColor) Miw(120px) Miw(100px)--pnclg Bgc($lv1BgColor) fi-row:h_Bgc($hoverBgColor) D(tbc)" data-test="fin-col"><span>85,528,000</span></div>
<div class="Ta(c) Py(6px) Bxz(bb) BdB Bdc($seperatorColor) Miw(120px) Miw(100px)--pnclg D(tbc)" data-test="fin-col"><span>91,244,000</span></div>
<div class="Ta(c) Py(6px) Bxz(bb) BdB Bdc($seperatorColor) Miw(120px) Miw(100px)--pnclg Bgc($lv1BgColor) fi-row:h_Bgc($hoverBgColor) D(tbc)" data-test="fin-col"><span>91,247,000</span></div>
</div>
<div></div>

在我的代码中,我使用Selenium来处理页面。不确定这是否是最好的方式,但对于urlopen等其他库,我无法看到HTML内容。我可以打开页面,点击接受按钮,但在那之后,我不知道如何在第一个div中导航;AttributeError:"NoneType"对象没有属性"get_text">

import requests
from urllib.request import urlopen, Request
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Firefox()
url = "https://finance.yahoo.com/quote/BAC/financials?p=BAC"
driver.get(url)
html = driver.page_source
soup = BeautifulSoup(html, "html.parser")
# Click accept button
aceitar = driver.find_element(By.NAME, "agree")
aceitar.click()
# Find the div of the Revenue row <div class="" data-test="fin-row">
primeiraLinha = soup.find("div", {"class":""})
print(primeiraLinha.get_text())

顺便说一句,我认为硒使这个过程非常缓慢。

这里有一个Selenium解决方案,可以在pandas数据帧中获取整个表。

需要导入

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import pandas as pd

启动web驱动程序

# Replace your CHROME DRIVER path here
chrome_path = r"C:UsershpoddarDesktopToolschromedriver_win32chromedriver.exe"
s = Service(chrome_path)
driver = webdriver.Chrome(service=s)

获取页面

driver.get('https://finance.yahoo.com/quote/BAC/financials?p=BAC')

等待表加载

WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, '//div[@class="D(tbhg)"]')))

获取标题行

headers_elem = driver.find_elements(By.XPATH, '//div[@class="D(tbhg)"]/div/div')
col_headers = [header.text for header in headers_elem]
df = pd.DataFrame(columns = col_headers)
df

输出:

Empty DataFrame
Columns: [Breakdown, TTM, 12/30/2021, 12/30/2020, 12/30/2019, 12/30/2018]
Index: []

从表中获取行

在这里,表中的每一行都存储在rows

rows = driver.find_elements(By.XPATH, '//div[@class="D(tbrg)"]//div[@data-test="fin-row"]')
for row in rows:
row_values = row.find_elements(By.XPATH, 'div/div')
df.loc[len(df)] = [row_value.text for row_value in row_values]

输出:

这给了我们预期的输出:

018年12月30日>td style="text-align:left;">90742000>td style="ext-align:left;">85528000>td style="text-align:lefttd style="text-align:right;">4>td style="ext-align:left基本EPStd style="text-align:right;">10td style="text-align:right;">11td style="text-align:right;">12>47080000>td style="text align:left标准化收入>28018000>81447000td style="text-align:right;">19td style="text-align:right;">20td style="text-align:right;">21/table>
Breakdown
0总收入8911300091244000
1信贷损失准备金
2无息支出3特别收入费用税前收入5税收条款35210006净收入普通股股东7Com股东可用的稀释NI26565000
9稀释每股收益基本平均股票稀释平均股票INTEREST_INCOME_AFER_PROVISION_FOR_LOAN_LOSS13持续经营净收入;已停止操作28018000
15货币市场投资总额16对账折旧17持续经营净收入少数股东净权益319780001789400027430000
18不包括商誉的异常项目总数异常项目总数计算税率特殊项目的税收影响

最新更新