Мой скребок Python BeautifulSoup для данных финансовых котировок yahoo сломался. Что — то изменилось за последнюю неделю?

#python #beautifulsoup

Вопрос:

 def get_fy(ticker, outFile):
    global retry
    # print ( "get_fy processing", ticker, ", retry =", retry )
    try:

        # create a web driver instance
        p1 = "http://finance.yahoo.com/quote/"
        p2 = "?p="
        p3 = "amp;.tsrc=fin-srch-v1"
        print(p1 ticker p2 ticker)
        r = urlopen(p1 ticker p2 ticker)
        bsObj = BeautifulSoup(r,"html5lib")
        # bsObj = BeautifulSoup(r.read())
        titleList = bsObj.findAll("title")
        # title = title_re.search(r.data)
        if not titleList or titleList[0].get_text().find('Stock Price')<0:
            print ("found", len(bsObj.get_text()), "bytes" )
            print ("found title at", bsObj.get_text().find("<title>"))
            print ("found", len(bsObj.findAll("td")), "td objects")
            print (bsObj.get_text()[:70])
            if titleList: print("found titleList[0]:", titleList[0])
            else: print("titleList was not found")
            #dump = open('dump.html', 'w')
            #dump.write(bsObj.get_text())
            #dump.close()
            if retry > 2: return False
            retry = retry 1
            time.sleep(10)
            print ("retry count", retry, "for", ticker )
            return get_fy(ticker,outFile)

        elements = bsObj.findAll("td")
 

процесс F (http://finance.yahoo.com/quote/F?p=F) дает:

 found 140676 bytes
found title at -1
found 0 td objects
▼ì½ízÓÈÒ(ú⌂]…ð♀`¿XŠ¾-ÛcX!       ♥k%„�♦سxyóÈ’∟k!K▲INb2ÞϹ�s{çJNUuKÖ—C↕☻3³ö
titleList was not found
retry count 1 for F
 

Комментарии:

1. Должен ли у этого быть тег python 2?

2. Нет, я не вижу ничего специфичного для Python 2.

Ответ №1:

Похоже, что код сначала пытается получить тег заголовка HTML для данного тикера, а затем получить одну из таблиц. Вы могли бы сделать это следующим образом:

 from bs4 import BeautifulSoup
import requests

def get_fy(ticker, outFile):
    url = f'https://finance.yahoo.com/quote/{ticker}/key-statistics?p={ticker}'
    print(url)

    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'}
    r = requests.get(url, headers=headers)
    soup = BeautifulSoup(r.content, "html5lib")

    title = soup.title.text
    print(title)

    for tr in soup.table.find_all('tr'):
        row = [td.text for td in tr.find_all('td')]
        print(f'{row[0]:30}  {row[1]}')
    
get_fy("LMT", "test.txt")

    
 

Что будет отображаться:

 https://finance.yahoo.com/quote/LMT/key-statistics?p=LMT
Lockheed Martin Corporation (LMT) Valuation Measures amp; Financial Statistics
Market Cap (intraday) 5         106.48B
Enterprise Value 3              115.73B
Trailing P/E                    15.46
Forward P/E 1                   13.74
PEG Ratio (5 yr expected) 1     2.79
Price/Sales (ttm)               1.61
Price/Book (mrq)                16.87
Enterprise Value/Revenue 3      1.75
Enterprise Value/EBITDA 7       11.33
 

Там всегда должен быть только один <title> тег, поэтому .find_all() вызов не требуется (он всегда даст вам только один список элементов). Сайту также требовалось добавить пользовательский агент, прежде чем возвращать подходящий HTML.

Комментарии:

1. Мартин, спасибо за помощь. Мне удалось импортировать пакет запросов, и это сработало. Когда я перешел к элементам <td> в разделе <td> финансы. yahoo.com/quote/LMT/key-statistics?p=LMT

2. Не за что! Для этого URL-адреса вам, похоже, нужно добавить агента пользователя в запрос, прежде чем он что-либо вернет. Я обновил сценарий, чтобы показать вам, как получить информацию из первой таблицы.

3. Мартин, еще раз спасибо. Я реализовал код, который вы предоставили. Это поиск названия, но в нем 0 строк, я работаю на ПК с mac. Нужно ли мне изменять заголовок?

4. Нет, заголовок предназначен только для того, чтобы притвориться перед сервером, что вы настоящий браузер. Я только что перепроверил сценарий, и он все еще отлично работает для меня? (на окнах)