Блог им. tomas_b88

Парсинг текущего значения цены акций Python.

 
Захотелось реализовать несколько идей для быстрого расчета по позициям акций и  для этого мне нужно было чтобы скрипт на python постоянно получал обновленное значение цены. Например раз в три секунды. Искал решение и нашел похожий пример с парсингом любой информации в интернете на python с применением блиотек requests и beautiful soup, (bs4)


На примере тикера GAZP продемонстрирую как можно спарсить текущий курс (например с гугла.)

 Кому лень читать всё что я тут написал можно скопипастить полный код в конце статьи :)


Парсинг текущего значения цены акций Python.



Для начала нужно установить нужные библиотеки, в консоли пишем : 
 

pip install requests bs4
 

Теперь перейдем к коду. 

Импортируем то, что установилось. Также нам понадобится библиотека time для задержки запросов по времени.

import requests  # для URL запроса
from bs4 import BeautifulSoup  # для работы с HTML
import time  # для установки задержки в цикле программы

Можно сразу задержку вынести в отдельную переменную, для экспериментов. 

sleep = 3  # время задержки

Идем на сайт гугл финансы и копируем ссылку,
Ссылка помещается в переменную GAZP
(для удобства читаемости кода я переносил строку ссылки через "\".)

# ссылка на тикер (Я использовал сайт google finance)
    GAZP = "https://www.google.com/" \
           "finance/quote/" \
           "GAZP:MCX?sa=X&ved=2ahUKEwjK5-z-yJLyAhUhpIsKHXbMBh0Q_AUoAXoECAEQAw"

Для формирования URL запроса нам потребуются заголовки my user agent, чтобы запрос не был воспринят гуглом как БОТ- запрос.
Эту строчку можно получить набрав в гугле поисковый запрос my user agent и скопировать то что будет сверху

Парсинг текущего значения цены акций Python.

Сохраняем эту строку в переменную headers

# заголовки для URL запроса.(добавляется к ссылке при URL запросе)
    headers = {
        'user agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) "
                      "AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/91.0.4472.135 Safari/537.36"}

Теперь у нас есть всё для того чтобы сформировать запрос. Результат запроса помещается в переменную, которая будет содержать всю HTML разметку данной страницы.

# запрашиваем страницу по ссылке и помещаем в переменную html
    html = requests.get(GAZP, headers)

Воспользуемся библиотекой BeautifulSoup чтобы спарсить все тэги из html, который был получен строчкой выше. 

# парсим данные в переменную soup
    soup = BeautifulSoup(html.content, 'html.parser')

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

Парсинг текущего значения цены акций Python.


Мы видим что наш объект помещен в тэг div с признаком class=«YMlKec fxKbKc» вот по этому признаку и найдем интересующий нас фрагмент страницы. Результат поиска записываем в переменную convert

# находим интересующий нас тэг с текущей ценой акции
    # (В браузере используем просмотр кода элемента для того чтобы найти это значение)
    convert = soup.findAll('div', {'class': 'YMlKec fxKbKc'})

После того как мы получили нужную нам строчку берем её первый элемент (первый считается с индексом[0]) и записываем полученную строку в переменную price. Но нужно еще сделать пару преобразований. Если мы распечатаем значение price то напечатается строка вида ₽286.05

Для начала избавимся от символа рубля в начале строки срезом этой строки [1:]

И также нам нужно конвертировать эту строку в число в формате float, так как сейчас она является текстом. 

# считываем 1й элемент как текст.
    # Делаем срез и избавляемся от знака ₽ в начале строки,
    # конвертируем строку в число типа float
    price = float(convert[0].text[1:])

Теперь мы можем работать с полученным значением. price :) 
Для проверки выведем на печать

print("Цена акции Газпром: ", price)

Создадим функцию update_ticker(): и поместим туда весь код, который мы написали выше. В конце функции укажем задержку по времени. Воспользуемся функцией sleep библиотеки time и передадим ей одноименный аргумент sleep, который мы объявили вначале программы. 

Для того чтобы функция повторялась вызовем её повторно прямо из этой же функции .

# устанавливаем задержку
time.sleep(sleep)
update_ticker()  # вызываем эту же функцию снова

Можно сделать и по другому, но это не боевой вариант а прототип, демонстрирующий возможности парсера с повторением запроса по таймеру. 

Функция готова и чтобы всё заработало вызываем её один раз в начале программы. Далее она вызывает сама себя с интервалом в sleep, 3 секунды. 

Полный код этого примера : 
import requests  # для URL запроса
from bs4 import BeautifulSoup  # для работы с HTML
import time  # для установки задержки в цикле программы

sleep = 3  # время задержки


def update_ticker():
    # ссылка на тикер (Я использовал сайт google finance)
    GAZP = "https://www.google.com/" \
           "finance/quote/" \
           "GAZP:MCX?sa=X&ved=2ahUKEwjK5-z-yJLyAhUhpIsKHXbMBh0Q_AUoAXoECAEQAw"

    # заголовки для URL запроса.(добавляется к ссылке при URL запросе)
    headers = {
        'user agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) "
                      "AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/91.0.4472.135 Safari/537.36"}

    # запрашиваем страницу по ссылке и помещаем в переменную html
    html = requests.get(GAZP, headers)

    # парсим данные в переменную soup
    soup = BeautifulSoup(html.content, 'html.parser')

    # находим интересующий нас тэг с текущим курсом
    # (В браузере используем просмотр кода элемента для того чтобы найти это значение)
    convert = soup.findAll('div', {'class': 'YMlKec fxKbKc'})

    # считываем 1й элемент как текст.
    # Делаем срез и избавляемся от знака ₽ в начале строки,
    # конвертируем строку в число типа float
    price = float(convert[0].text[1:])

    print("Цена акции Газпром: ", price)
    # устанавливаем задержку
    time.sleep(sleep)
    update_ticker()  # вызываем эту же функцию снова


update_ticker()


 
★19
25 комментариев
две мои любимые библиотеки для работы BeautifulSoup и Selenium ))
avatar
Mantis, до сегодняшнего дня и не знал что это такое ) теперь мне тоже это нравится  буду парсить всё подряд 
avatar
шляпа по названию класса парсить. поменяют id и привет.
если уж хочется, то лучше разобрать xml с yahoo finance. 
avatar
DoubleBubble, а как еще можно 
avatar
tomas_b88, вот открой в браузере (https://query2.finance.yahoo.com/v7/finance/quote?symbols=CHMF.ME) и потом разбирай спокойно любым xml парсером. все параметры четкие и не меняются. плюс есть ещё и всякие другие плюшки в виде % изменения, PE, PB (но не везде)
avatar
DoubleBubble, попробую :)
avatar
Теперь у нас есть всё для того чтобы сформировать запрос. Результат запроса помещается в переменную, которая будет содержать всю HTML разметку данной страницы.
.....
Тупиковый вариант. HTML код страниц достаточно часто меняется, и потом хрен найдешь эту ссылку.
avatar
3Qu, ну да.  в принципе можно генерить новую просто поисковым запросом 
avatar
tomas_b88, это утопия. см. выше как надо :)
avatar
DoubleBubble, xml с yahoo finance? ) ок попробую переделать 
avatar
Я никогда не смотрел, но сдаётся мне, что у гугла точно есть API, для таких вещей. 

Вот первая ссылка.

support.google.com/docs/answer/3093281?hl=ru
avatar
Gravizapa, о, ниче себе. спасибо.  написано что 
MCX Московская биржа В режиме реального времени

попробую использовать :) 
avatar
tomas_b88, Прежде всего, найди какие ограничения для бесплатного использования. А то там может 10 запросов в день)
avatar
alor open api, REST-клиент для Python есть в примерах, websocket-клиента — чтобы уж совсем кошерный реалтайм — сделать недолго. 
avatar
tashik, Благодарю за наводку ) тоже рассмотрю поближе 
avatar
Я понял, чтобы собрать пул годных советов по решению задачи, нужно попробовать выложить на коленке собранный вариант 
avatar
Не проще текущую цену напрямую скачивать с московской бирже? Через запросы ISS Queries (moex.com)

 

avatar
Riskplayer, может и проще ) не пробовал, попробую обязательно все предложенные варианты :) 
avatar
Слишком сложная связка. Попробуй pandas, или pandas-finance. В pandas-finance реализован доступ к фондоврй секции moex. Фьючерсы там криво загружаются. Все примеры, как работать с библиотекой, есть в сети.
Что касается pandas, то через библиотеку можно выгружать csv данные по инструментам через moex api. Но там придется много обработок делать.
avatar
Артем, Спасибо! буду пробовать
avatar
tomas_b88, Есть еще библиотека apimoex. Тоже удобно.
avatar
Riskplayer, наткнулся на нее вчера тоже. пока на заметочку оставлю. Пригодится для дальнейших экспериментов. Сейчас я решил пока остановиться на варианте с json запроса с yahoo. Попробовал оч. удобно и под эту задачу норм подходит и заморочек минимум. получаем json вытаскиваем нужную строчку.
avatar
можно проще через power query запарсить инфо
Игнатов Виталий, можно но скрипт планируется делать автономным без GUI и запускать его на debian. помимо парсера там будут крутиться еще пара скриптов. На самом деле способов великое множество оказалось. я выбрал способ получения инфы с yahoo либо через библиотеку yfinance либо через свой класс. Остановился на своем т.к. он заточен только под то что нужно и я не нашел некоторых функций в yfinance. 
Тут сравнил два способа smart-lab.ru/blog/713434.php
avatar
попробовал покачто через json запрос на yahoo 
Написал пример ТУТ  
avatar

теги блога tomas_b88

....все тэги



UPDONW
Новый дизайн