Как достать path из svg с помощью BeautifulSoup

Осуществляю парсинг сайта, который показывает погоду: https://www.foreca.ru/Russia/Moscow
Все, что нужно достал, но не получается достать направление ветра
По факту, зацепиться не за что, кроме как залезть в <svg>, там найти <path> с иконками и сравнивать направления


Структура сайта, где иконки с ветром такая (каждая иконка - <path>):

<div id="meteogram">
    <svg height="330" version="1.1" width="626" xmlns="http://www.w3.org/2000/svg"...>
        <path style="" fill="#88cc4f" stroke="#88cc4f" d="M26,307.5H32V310.5L38,306L32,301.5V304.5H26V307.5" transform="matrix(0,-1,1,0,-274,338)"></path>

Мне нужно достать все <path>, но когда я запускаю wind_route = soup.find("div", class_="meteogram") мне возвращается только <div id="meteogram"></div>. Может, содержимое этого блока генерируется динамически и нужно использовать селениум?


Как достать все <path>, либо же можно спарсить направление ветра как-то по другому через foreca?


Ответы (1 шт):

Автор решения: gil9red

Посмотрел как формируется график на сайте, хоть вы и видите там svg, но он рендерится при загрузке сайта, а для этого нужен движок javascript и все-равно неудобно будет работать с svg :) Но есть решение лучше

Сами же данные находятся в куске javascript - список объектов, где поле ws соответствует значению стрелки, а wd градус наклона стрелки:

var mgdata = [{d:'пн', di: 0, dl: 'Понедельник', dt: '9.8.', hi: '21:00', h: '21', s: 'n000', r: 0.00, rl: 0.00, rs: 0.00, wx: 'Ясно', ws: 2, wd: 45, t: 24}, ...

Шаги:

  1. Извлечь значение mgdata из кода javascript
  2. Вытащить данные для парсинга
    1. Используем регулярное выражение
    2. Для удобства преобразовываем данные в питоничьи данные, но есть проблема с ключами словаря, в js их можно без кавычек оформить, а в питоне кавычки потребуются
    3. Сделаем функция препроцесса, чтобы добавить кавычки, тогда ast.literal_eval сможет распарсить строку и получим список из словарей
  3. Вывести результат парсинга

Решение:

import ast
import re

import requests


def preprocess_js(text: str) -> str:
    return re.sub(r'(\w+):', r'"\1":', text)


rs = requests.get('https://www.foreca.ru/Russia/Moscow')

m = re.search(r'var mgdata = (.+);', rs.text)
js_text = m.group(1)
print(js_text)
# [{d:'пн', di: 0, dl: 'Понедельник', dt: '9.8.', hi: '21:00', h: '21', s: 'n000', r: 0.00, rl: 0.00, rs: 0.00, wx: ...

js_text = preprocess_js(js_text)
print(js_text)
# [{"d":'пн', "di": 0, "dl": 'Понедельник', "dt": '9.8.', "hi": '"21":00', "h": '21', "s": 'n000', "r": 0.00, "rl" ...

items = ast.literal_eval(js_text)
for x in items:
    print(x['dl'], x['ws'], x['wd'])

Результат:

Понедельник 2 45
Вторник 2 45
Вторник 2 90
Вторник 3 135
Вторник 3 180
...
Суббота 3 270
Суббота 2 315
Суббота 2 270
Суббота 2 225
Воскресенье 2 225
→ Ссылка