2016-02-16 1 views
4

Я пытаюсь скопировать данные из отчетов о доходах на Yahoo Finance с использованием Python. В частности, скажем, я хочу most recent figure of Net Income of Apple.Scrape Yahoo Финансовый отчет о прибылях и убытках с Python

Данные структурированы в связке вложенных HTML-таблиц. Я использую модуль requests для доступа к нему и получения HTML.

Я использую BeautifulSoup 4 для просеивания через HTML-структуру, но я не могу понять, как получить цифру.

Here - это скриншот анализа с Firefox.

Мой код до сих пор:

from bs4 import BeautifulSoup 
import requests 

myurl = "https://finance.yahoo.com/q/is?s=AAPL&annual" 
html = requests.get(myurl).content 
soup = BeautifulSoup(html) 

Я попытался с помощью

all_strong = soup.find_all("strong") 

, а затем получить 17-й элемент, который, случается, одна из которых фигуру я хочу, но это, кажется, далеко от элегантный. Что-то вроде этого:

all_strong[16].parent.next_sibling 
... 

Конечно, цель состоит в том, чтобы использовать BeautifulSoup для поиска Название фигуры мне нужно (в данном случае, «Чистая прибыль»), а затем захватить цифры сами в той же строки HTML-таблицы.

Я был бы очень признателен за любые идеи о том, как решить эту проблему, имея в виду, что я хотел бы применить решение для извлечения множества других данных с других страниц Yahoo Finance.

РЕШЕНИЕ/РАСШИРЕНИЕ:

Решение по @wilbur ниже работал и я расширил на нем, чтобы иметь возможность получить значения для любой фигуры доступны на любой страниц Financials (т.е. Income Statement , Balance Sheet и Cash Flow Statement) для любая листинговая компания. Моя функция заключается в следующем:

def periodic_figure_values(soup, yahoo_figure): 

    values = [] 
    pattern = re.compile(yahoo_figure) 

    title = soup.find("strong", text=pattern) # works for the figures printed in bold 
    if title: 
     row = title.parent.parent 
    else: 
     title = soup.find("td", text=pattern) # works for any other available figure 
     if title: 
      row = title.parent 
     else: 
      sys.exit("Invalid figure '" + yahoo_figure + "' passed.") 

    cells = row.find_all("td")[1:] # exclude the <td> with figure name 
    for cell in cells: 
     if cell.text.strip() != yahoo_figure: # needed because some figures are indented 
      str_value = cell.text.strip().replace(",", "").replace("(", "-").replace(")", "") 
      if str_value == "-": 
       str_value = 0 
      value = int(str_value) * 1000 
      values.append(value) 

    return values 

yahoo_figure Переменная является строкой. Очевидно, это должно быть то же имя, что и на Yahoo Finance. Чтобы передать переменную soup, я использую следующую функцию: первый

def financials_soup(ticker_symbol, statement="is", quarterly=False): 

    if statement == "is" or statement == "bs" or statement == "cf": 
     url = "https://finance.yahoo.com/q/" + statement + "?s=" + ticker_symbol 
     if not quarterly: 
      url += "&annual" 
     return BeautifulSoup(requests.get(url).text, "html.parser") 

    return sys.exit("Invalid financial statement code '" + statement + "' passed.") 

использования Sample - Я хочу, чтобы получить прибыль налоговых расходов Apple Inc. из последних доступных отчетов о доходах:

print(periodic_figure_values(financials_soup("AAPL", "is"), "Income Tax Expense")) 

Выхода: [19121000000, 13973000000, 13118000000]

Вы также могли бы получить дату конца периода от soup и создать словарь WHe а датами являются ключи, а цифры - значения, но это слишком долго. Пока это работает для меня, но я всегда благодарен за конструктивную критику.

ответ

3

Это сделано немного сложнее, потому что в «чистой прибыли» в заключенной в <strong> теге, так нести со мной, но я думаю, что это работает:

import re, requests 
from bs4 import BeautifulSoup 

url = 'https://finance.yahoo.com/q/is?s=AAPL&annual' 
r = requests.get(url) 
soup = BeautifulSoup(r.text, 'html.parser') 
pattern = re.compile('Net Income') 

title = soup.find('strong', text=pattern) 
row = title.parent.parent # yes, yes, I know it's not the prettiest 
cells = row.find_all('td')[1:] #exclude the <td> with 'Net Income' 

values = [ c.text.strip() for c in cells ] 

values, в этом случае, будет содержать три ячейки таблицы в том, что «чистый доход» подряд (и, я мог бы добавить, может быть легко преобразован в Интс - мне просто нравилось, что они держали «» как строки)

In [10]: values 
Out[10]: [u'53,394,000', u'39,510,000', u'37,037,000'] 

Когда я тестировал на Алфавит (GOOG) - это не работает, потому что они не отображают I (https://finance.yahoo.com/q/is?s=GOOG&annual), но когда я проверил Facebook (FB), значения были возвращены правильно (https://finance.yahoo.com/q/is?s=FB&annual).

Если вы хотите создать более динамичный сценарий, вы можете использовать строку форматирования для форматирования URL с тем, что фондовый символ вы хотите, как это:

ticker_symbol = 'AAPL' # or 'FB' or any other ticker symbol 
url = 'https://finance.yahoo.com/q/is?s={}&annual'.format(ticker_symbol)) 
+0

Спасибо большое. До сих пор отлично работает. Теперь мне просто нужно сделать его немного более динамичным. Не только в отношении акций, но и других финансовых данных на одном складе, а также для проверки последних данных и т. Д. Но это отличное начало. – JohnGalt

Смежные вопросы