ОБНОВЛЕНИЕ
Ответ Джека Флитинга, вероятно, является лучшим подходом для решения вопроса ОП.
Мой ответ работает, но он бледнеет по сравнению с подходом Джека. Я оставляю здесь свой ответ, потому что я хочу, чтобы он служил заполнителем, чтобы помочь другим, которым необходимо решить аналогичную проблему в будущем.
ОРИГИНАЛЬНЫЙ ОТВЕТ
Вот еще один ответ, который, вероятно, может быть получен кем-то с лучшими навыками приготовления супа, чем я.
Я поместил очищенные данные в 2 словаря с именами balance_sheet_dict и financials_dict . Я также очистил даты, связанные со столбцами, потому что я использовал бы их в некоторой другой функции. Я также переформатировал эти даты с% m /% d /% Y до% m% d% Y.
Я также использовал супы find_all_next (tag_name, limit = int), чтобы собирать только требуемые вложенные теги. Вы можете отрегулировать этот лимит, чтобы собирать нужные вам предметы из таблиц.
В целом это был интересный вопрос, который потребовал некоторых дополнительных размышлений. Спасибо за публикацию вопроса.
import requests
from datetime import datetime
from bs4 import BeautifulSoup
import re as regex
operating_income_or_loss_keys = []
operating_income_or_loss_values = []
def get_operating_income_or_loss(soup):
for rows in soup.find_all('div', {'class': 'D(tbr)'}):
for date_row in rows.find_all('div', {'class': 'D(ib)'}):
chart_dates = date_row.find_all_next('span', limit=8)
for dates in chart_dates[1:]:
if dates.text == 'ttm':
operating_income_or_loss_keys.append(dates.text)
else:
date_format = regex.match(r'(\d{1,2}/\d{2}/\d{4})', dates.text)
if date_format:
reformatted_date = datetime.strptime(dates.text, '%m/%d/%Y').strftime('%m%d%Y')
operating_income_or_loss_keys.append(reformatted_date)
for sub_row in rows.find_all('div', {'class': 'D(tbc)'}):
for row_item in sub_row.find_all('span', {'class': 'Va(m)'}):
if row_item.text == 'Operating Income or Loss':
operating_income_or_loss = row_item.find_all_next('span', limit=len(operating_income_or_loss_keys))
for item in operating_income_or_loss[1:]:
if len(item) == 0 or item.text == '-':
operating_income_or_loss_values.append('no value provided')
else:
operating_income_or_loss_values.append(item.text)
return
total_assets_values = []
total_current_liabilities = []
balance_sheet_keys = []
def get_total_assets(soup):
for rows in soup.find_all('div', {'class': 'D(tbr)'}):
for date_row in rows.find_all('div', {'class': 'D(ib)'}):
if date_row.text == 'Breakdown':
chart_dates = date_row.find_all_next('span', limit=8)
for dates in chart_dates[1:]:
date_format = regex.match(r'(\d{1,2}/\d{2}/\d{4})', dates.text)
if date_format:
reformatted_date = datetime.strptime(dates.text, '%m/%d/%Y').strftime('%m%d%Y')
balance_sheet_keys.append(reformatted_date)
for rows in soup.find_all('div', {'class': 'D(tbr)'}):
for sub_row in rows.find_all('div', {'class': 'D(tbc)'}):
for row_item in sub_row.find_all('span', {'class': 'Va(m)'}):
if row_item.text == 'Total Assets':
total_assets = row_item.find_all_next('span', limit=len(balance_sheet_keys))
for item in total_assets:
if len(item) == 0 or item.text == '-':
total_assets_values.append('no value provided')
else:
total_assets_values.append(item.text)
return
def get_total_current_liabilities(soup):
for rows in soup.find_all('div', {'class': 'D(tbr)'}):
for sub_row in rows.find_all('div', {'class': 'D(tbc)'}):
for row_item in sub_row.find_all('span', {'class': 'Va(m)'}):
if row_item.text == 'Total Current Liabilities':
current_liabilities = row_item.find_all_next('span', limit=len(balance_sheet_keys))
for item in current_liabilities:
if len(item) == 0 or item.text == '-':
total_current_liabilities.append('no value provided')
else:
total_current_liabilities.append(item.text)
return
urls = ['https://finance.yahoo.com/quote/AAPL/balance-sheet?p=AAPL',
'https://finance.yahoo.com/quote/AAPL/financials?p=AAPL']
for url in urls:
stock_symbol = url.rpartition('?p=')[-1]
if 'balance-sheet' in url:
response = requests.get(url)
soup = BeautifulSoup(response.text, "html.parser")
get_total_assets(soup)
get_total_current_liabilities(soup)
balance_sheet_dict = {k: v for k, v in zip(balance_sheet_keys, zip(total_assets_values,total_current_liabilities))}
print('*' * 10, f'Balance sheet results for {stock_symbol}', '*' * 10)
for key, values in balance_sheet_dict.items():
total_asset = values[0]
current_liabilities = values[1]
print (f'Year: {key}, Total Asset: {total_asset}')
print (f'Year: {key}, Current liabilities: {current_liabilities}')
# output
********** Balance sheet results for AAPL **********
Year: 09292018, Total Asset: 365,725,000
Year: 09292018, Current liabilities: 116,866,000
Year: 09292017, Total Asset: 375,319,000
Year: 09292017, Current liabilities: 100,814,000
Year: 09292016, Total Asset: 321,686,000
Year: 09292016, Current liabilities: 79,006,000
elif 'financials' in url:
response = requests.get(url)
soup = BeautifulSoup(response.text, "html.parser")
get_operating_income_or_loss(soup)
financials_dict = {k: v for k, v in zip(operating_income_or_loss_keys, operating_income_or_loss_values)}
print('*' * 10, f'Financials results for {stock_symbol}', '*' * 10)
for key, value in financials_dict.items():
print (f'Year: {key}, Operating income or loss: {value}')
# output
********** Financials results for AAPL **********
Year: ttm, Operating income or loss: 64,423,000
Year: 09292018, Operating income or loss: 70,898,000
Year: 09292017, Operating income or loss: 61,344,000
Year: 09292016, Operating income or loss: 60,024,000
Ссылка на ваш комментарий по запросу словаря с именем balance_sheet_dict за 2016 год:
for key, values in balance_sheet_dict.items():
if key.endswith('2016'):
total_asset = values[0]
current_liabilities = values[1]
print (f'Year: {key}, Total assets: {total_asset}, Total current liabilities: {current_liabilities}')
# output
Year: 09292016, Total assets: 321,686,000, Total current liabilities: 79,006,000