Всех приветствую! Хочу рассказать, как мне удалось примененить библиотеку pandas для парсинга и обработки метеорологических данных сайта Яндекс.Погоды. Отмечу, что это моя первая статья для Habr, строго не судите.
Краткая предыстория. Так случилось, что мне пришлось вести telegram-канал о погоде, практически сразу встал вопрос как сократить время на поиск и анализ данных с основных метеорологических сайтов, чтобы получать всё just-in-time на свой компьютер. Иными словами, была цель сделать небольшую автоматизацию.
Яндекс.Погода
В настоящий момент существует некоторое количество стандартных методик получения данных с сайта (библиотеки requests), но мне удалось воспользоваться встроенным методом read_html() из библиотеки pandas и «прочитать» HTML-таблицу сразу в DataFrame, использую Jupiter Notebook.
Базовый синтаксис метода:
df = pd.read_html('ссылка')
Отдельно отмечу, что при чтении методом read_html() не улавливала ошибки при помощи конструкции try - except, так как, во-первых сам сайт Я.Погоды работает достаточно стабильно, а, во-вторых, цель была лишь получить данные.
Итак, после анализа полученной таблицы, стало очевидно, что необходимые нам данные лежат в ячейках [1]-[9]. Собираем их в DataFrame, с которым можно работать при помощи concat():
ya_new=pd.concat([ya_df[0],ya_df[1],ya_df[2],ya_df[3],ya_df[4],ya_df[5],ya_df[6],ya_df[7],ya_df[8],ya_df[9]],ignore_index=True)
Получаем таблицу с «сырыми» данными:
Ситуация стала лучше! Было заметно, что данные организованы достаточно структурно, отсутствуют пропуски в основных столбцах, соответсвенно появился некоторый план дальнейшей работы:
Обработать столбец с температурой temp, чтобы получить нижнюю и верхнюю границу температуры при помощи регулярных выражений (и небольшой магии)
Обработать столбец wind при помощи регулярных выражений, чтобы получить значение ветра (без направления)
Придумать и реализовать обработку колонки с температурой по ощущениям (метеорологи называют ее) t_eff
Собрать всё в итоговый датафрейм.
Обработка столбца temp заключалась в том, чтобы пройдя циклом построчно в столбце датафрейма, найти и записать в список элементы, соответствующие шаблону '[+ -]\d{1,2}\…[+ -]\d{1,2}'. Как следует разобраться в регулярках мне помогло это видео.
for i in range(0,ya_new.shape[0]):
t_str=ya_new['temp'][i]
temp_str=re.search(r'[+ -]\d{1,2}\…[+ -]\d{1,2}',t_str) #поиск по шаблону при помощи метода search() библиотеки re
temp_clean.append(temp_str.group(0))
Аналогичным образом был реализован цикл для обработки столбца wind:
for i in range(0,ya_new.shape[0]):
w_str=ya_new['wind'][i]
wind_str=re.search(r'\d{1,2},\d',w_str) #поиск по шаблону при помощи метода search() библиотеки re
wind_clean.append(wind_str.group(0))
Хотелось бы остановиться на обработке столбца t_eff. Столбец содержит строку, в которой дважды повторено одно и то же значение. В начале каждой такой строки может стоять «+», «-» либо ничего (если значение температуры 0). Реализация разделения:
t_eff=[]
for i in range(0,ya_new.shape[0]):
string=ya_new['t_eff'][i] #идём по элементам столбца
if string[0]=='−': #если сначала идет «-»
s_1=re.sub('[^0-9]','', string) #удаляем все, что не цифра
s_fin='−'+s_1[:len(s_1)//2] #сохраняем в новую строку «половину» длины строки со знаком «-»
if string[0] != '−': #аналогично делаем для ситуации, если там не «-», а «+» или ничего.
s_1=re.sub('[^0-9]','', string)
s_fin=s_1[:len(s_1)//2]
t_eff.append(s_fin)
Отдельно было заменен знак % в столбце влажности и обработаны типы данных и добавлен столбец со средней температурой:
#поработаем с форматами
ya_full[['t_down','t_up','wet']]=ya_full[['t_down','t_up','wet']].astype('int')
ya_full['wind']=ya_full['wind'].astype('float')
ya_full['t_eff']=ya_full['t_eff'].astype('int')
#считаем среднюю температуру
ya_full['t_mean']=(ya_full['t_up']+ya_full['t_down'])/2
...и собран итоговый датафрейм при помощи concat():
ya_full=pd.concat([list_days,temp_fin,ya_new[['press','wet']],wind_fin,temp_eff,ya_new['weather']],axis=1)
С такой табличкой уже можно было что угодно: считать средние по разным сайтам, строить графики, анализировать и т.д. В следующей статье расскажу про обработку данных сайта Гидрометцентра (там всё оказалось сложнее), полный код реализации из данного кейса можно посмотреть на моём github.