Мелкая питонячая радость #11: реактивное программирование, парсинг страниц и публикация моделей маши
- пятница, 23 октября 2020 г. в 00:32:17
На этой неделе мы посмотрим, как можно работать чуточку быстрее, чем вчера. Разбираемся и внедряем в свои проекты пайплайны реактивного программирования, автоматически потрошим тексты и превращаем модели машинного обучения в интерактивные веб приложения.
И еще один способ писать программы — реактивное программирование. Детальное описание этой инженерной концепции со всеми подробностями можно посмотреть в вики, а нам же нужно знать, что это способ представлять программу в виде набора данных, который перемещается через поток различных операций и фильтров к своему конечному состоянию.
Допустим, у вас есть коллекция ActiveRecord записей из СУБД. Вам нужно найти в этой коллекции определенные записи с определенными свойствами и применять к ним набор операций — что-то пересчитать, что-то после этого обновить в базе. В терминах rx вы бы сперва сформировали итератор/массив с первоначальным результатом запросов в базу, а потом бы описали пайплайн для прохождения записей чере все последующие шаги обработки.
В python из коробки реактивное программирование не поддерживается, для реализации этой концепции есть внешняя библитека rxpy.
Рассмотрим пример работы с JSON, в котором мы строим пайплайн из двух шагов и обрабатываем множество записей одним потоком.
import requests
import rx
import json
from rx import operators as ops
# Достаем JSON данные
content = requests.get('https://jsonplaceholder.typicode.com/users')
y = json.loads(content.text)
# Превращаем dict в специальную коллекцию для работы в rxpy
source = rx.from_(y)
# Эта функция будет принимать участие в нашем пайплайне
def filternames(x):
if (x["name"].startswith("C")):
return x["name"]
else :
return ""
# Собираем пайплайн в два шага — фильтрация коллекции и обработка значений
case1 = source.pipe(
ops.filter(lambda c: filternames(c)),
ops.map(lambda a:a["name"])
)
# Вешаем обработчики на события пайплайна
case1.subscribe(
on_next = lambda i: print("Got - {0}".format(i)), 8. RxPy — Examples
on_error = lambda e: print("Error : {0}".format(e)),
on_completed = lambda: print("Job Done!"),
)
К применению реактивного программирования в Python, конечно, есть вопросы — в языке и так из коробки есть map, reduce и filter, с помощью которых при необходимости можно соорудить свою обработку данных по схожему принципу, не привлекая к работе rxpy. Да и чтение кода с применением rxpy несколько усложняется.
Да, недостатки есть, но, как минимум, с концепцией реактивного программирования нужно быть знакомым — она активно применяется сегодня, например, в клиентском программировании на JS и Swift.
Newspaper
Несколько лет назад мне активно пришлось работать с извлечением текстов статей из разных сайтов. Задача несложная — получи ссылку на документ, выкачай HTML разметку, обработай ее парсером по типу beautiful soup — и вот тебе вся нужная информация. Минус в этом всем один — если сайтов много и все они разные, то работа программиста сводится к откровенно обезьяньему труду — ковырянии в HTML страниц и написании абсолютно однообразных парсеров по извлечению осмысленного контента.
На второй день возни с процессорами разметки и описания селекторов тегов я начал тихонько сходить с ума и задумался об автоматической потрошилке верстки. На глаза мне попалась либа newspaper.
Эта либа автоматически извлекает полезную инфу из новостей, журнальных и блоговых статей и прочих сайтов, где основной контент — это большие блоки текста. Библиотека сама анализирует страницы несложным алгоритмом, находит в коде осмысленный текст и извлекает его — вам вообще не потребуется описывать правила парсинга!
from newspaper import Article
url = 'http://fox13now.com/2013/12/30/new-year-new-laws-obamacare-pot-guns-and-drones/'
article = Article(url)
article.download()
#Скачали текст и запустил парсинг
article.parse()
>>> article.authors
['Leigh Ann Caldwell', 'John Honway']
>>> article.publish_date
datetime.datetime(2013, 12, 30, 0, 0)
# А вот тут лежит уже добытый текст! Все достается само, парсить ничего не надо
>>> article.text
'Washington (CNN) -- Not everyone subscribes to a New Year's resolution...'
>>> article.top_image
'http://someCDN.com/blah/blah/blah/file.png'
>>> article.movies
['http://youtube.com/path/to/link.com', ...]
Подразделения датасайнс повально работают в jupyter — идеальной среде для проведения исследований и экспериментов по анализу данных и машинному обучению.
Ппосле экспериментов с кодом и данными, настает момент, когда готовую математическую модель нужно откалибровать и донастроить с менеджерами проекта. Где-то менеджерам нужно попробовать разные входные параметры, где-то нужно посмотреть на графики — короче, мелких правок и тестов хватает.
Явно не все менеджеры сами в состоянии взять в руки jupyter и в нем работать с тем, что придумали датасайнтисты. Поэтому датасайнтистам приходится включаться в работу с менеджерами и тестировщиками, тратить время на отладку, вести длительную переписку с коллегами и вообще просаживать кучу времени на подгонку всяческих значений.
Streamlit позволяет взять вашу модель машинного обучения, прикрутить к ней всякие контролы и опубликовать одностраничное приложение, в котором все нуждающиеся могут напрямую задавать вашей модели любые необходимые параметры.
Streamlit — это фреймворк, который предельно упрощает создание одностраничных тестовых приложений для тех, кто хочет опубликовать свои модели машинного обучения.
На сегодня все, прошлые питонячие радости смотрите по ссылке.