Извлеките элементы SVG и заголовок из HTML с помощью BeautifulSoup

У меня есть фрагмент HTML, который я извлек с помощью BeautifulSoup, который содержит путь SVG и заголовок.

Мне интересно, есть ли способ извлечь текст заголовка и координаты из этого фрагмента.

<g class = "myclass"><title>mytitle</title><path d = "M -5, 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0" fill = "rgba(255,255,255, 0.1" stroke = "rgba(10, 158, 117, 0.8)" stroke-width = "3" transform = "translate(178.00000000000003, 201)"></path></g>

Ниже приведена функция, которая возвращает указанный выше фрагмент (rows).

def scrape_spatial_data(page):
    html = page.inner_html("body")
    soup = BeautifulSoup(html, "html.parser")
    rows = soup.select("g.myclass")
    return rows

Есть ли более чистый способ извлечь это с помощью BeautifulSoup?

Что такое страница? Кроме того, если веб-сайт является общедоступным, сообщите его URL-адрес и код, который вы используете для доступа к нему.

SIGHUP 08.06.2024 10:55

Страница @SIGHUP — это объект драматурга. URL-адрес, которым я не могу поделиться, поскольку он частный. browser = p.chromium.launch(headless=False)context = browser.new_context()page = context.new_page()page.goto(the_url)

felix1k 08.06.2024 11:03

Какой именно результат вы ожидаете? Под «координатами» вы имеете в виду значения в translate() или значение d=?

ggorlen 09.06.2024 15:33
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
92
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Разумным подходом к этому было бы вернуть словарь, который основан на именах атрибутов (из тега пути) и заголовке.

Я рекомендую использовать lxml (если он доступен) в качестве анализатора HTML для повышения производительности.

Попробуй это:

from playwright.sync_api import Page
from bs4 import BeautifulSoup as BS
from functools import cache

@cache
def get_parser():
    try:
        import lxml
        return "lxml"
    except Exception:
        pass
    return "html.parser"

def scrape_spatial_data(page: Page) -> dict[str, str]:
    html = page.inner_html("body")
    soup = BS(html, get_parser())
    result = {}
    if row := soup.select_one("g.myclass"):
        if t := row.select_one("title"):
            result["title"] = t.text
        if p := row.select_one("path"):
            result.update(p.attrs)
    return result

Для данных, показанных в вопросе, это покажет:

{
  "title": "mytitle",
  "d": "M -5, 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0",
  "fill": "rgba(255,255,255, 0.1",
  "stroke": "rgba(10, 158, 117, 0.8)",
  "stroke-width": "3",
  "transform": "translate(178.00000000000003, 201)"
}

У Playwright уже есть мощный API определения местоположения, который автоматически ожидает и работает на живой странице. Передача HTML-снимка страницы в BeautifulSoup только для того, чтобы сделать выбор, кажется ненужной, как покупка велосипеда только для того, чтобы кататься на нем, а не кататься на нем. С другой стороны, если HTML-код OP можно запрашивать статически, я бы не использовал Playwright, а вместо этого использовал бы requests для получения HTML-кода страницы без автоматизации браузера.

ggorlen 08.06.2024 16:04

@ggorlen Справедливый комментарий, но имейте в виду, в чем вопрос. BeautifulSoup вполне может быть неподходящим, но это (по-видимому) то, что требуется. Наше дело не в том, чтобы рассуждать, почему

SIGHUP 08.06.2024 17:03

Люди постоянно задают проблемы XY, и будущим посетителям, а также ОП, будет оказана медвежья услуга, если не упомянуть хотя бы о том, что может быть лучший способ сделать то, чего они хотят достичь. В любом случае, если вопрос о BS, то «Драматург» кажется лишним — одна или другая — я использую обе технологии уже много лет и никогда не видел варианта их объединения. Обычно это делают новички, не знакомые с библиотеками.

ggorlen 08.06.2024 17:06

@ggorlen 100%, я действительно новичок в обеих библиотеках - таблица, из которой я собираю данные, имеет кнопку «следующая страница», которую я использую драматург для навигации, а затем BS для моментального снимка этих данных. Если есть способ сделать то же самое в драматурге без использования BS, я бы хотел научиться

felix1k 09.06.2024 05:11

Если вы используете Playwright, нет необходимости использовать BeautifulSoup: выгрузка живого DOM в строку только для передачи в BS является антишаблоном и подвержена ошибкам. У Playwright есть полный набор локаторов и селекторов, которые работают с живой DOM и даже автоматически ждут действия перед операцией.

Итак, предполагая, что вы автоматизируете одностраничное приложение, избавьте себя от зависимостей, дополнительного синтаксиса, снижения производительности и потенциальных ошибок и придерживайтесь локаторов во всем:

from playwright.sync_api import sync_playwright # 1.44.0


svg = """<Your example SVG from the question, verbatim>"""


with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.set_content(svg) # for demonstration, normally use goto
    title = page.locator(".myclass title").text_content()
    coordinates = page.locator(".myclass path").get_attribute("transform")
    print(title, coordinates)
    browser.close()

Если вы хотите извлечь значения из аргументов translate(), вы можете использовать:

x, y = [float(x) for x in re.findall(r"[\d.]+", coordinates)]

Если вам нужны все атрибуты из элемента пути, вы можете использовать JS в браузере:

attrs = page.locator(".myclass path").evaluate("""
    el => Object.fromEntries([...el.attributes].map(e => [e.name, e.value]))
""")

С другой стороны, если вы очищаете статическую HTML-страницу, рассмотрите возможность отказа от Playwright в пользу запросов + BeautifulSoup.

Спасибо - попробую. Желание получить максимальную производительность, поэтому это будет полезно. Страница представляет собой динамическую HTML-страницу, поэтому, я думаю, понадобится драматург.

felix1k 10.06.2024 07:44

Другие вопросы по теме