Python: загрузка/очистка HTML-кода внутри «теневых корневых» узлов страниц.

Я пишу, чтобы попросить помощи в загрузке HTML-страницы, содержащей различные теневые корни.

Когда я пытаюсь загрузить эту страницу (https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_namespace_System.htm) с помощью python, результатом является базовый HTML без всех содержимое узла в теневом корне.

Это мой тестовый код:

from bs4 import BeautifulSoup as bs
import urllib.request

url_apex_namespace_System = 'https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_namespace_System.htm'

print(f"Retrive Html from {url_apex_namespace_System}")
fid = urllib.request.urlopen(url_apex_namespace_System)
webpage = fid.read().decode('utf-8')
bs_content = bs(webpage, "html")
print(webpage)

# If in the future id change, change it here
classLi = bs_content.find_all("div", {"id": "sfdc:seealso"},recursive=True)

И результат переменной classLi равен NoneType, потому что элемент находится внутри теневого корня.

Заранее спасибо

Я ожидаю, что: classLi должен содержать поисковый div внутри теневого корня.

Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Привет, люди RPA, это снова я и я несу подарки! В очередном моем приключении о том, как создавать ботов для облегчения рутины. Вот, думаю, стоит...
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
Учебник по веб-скрапингу
Учебник по веб-скрапингу
Привет, ребята... В этот раз мы поговорим о веб-скрейпинге. Целью этого обсуждения будет узнать и понять, что такое веб-скрейпинг, а также узнать, как...
Тонкая настройка GPT-3 с помощью Anaconda
Тонкая настройка GPT-3 с помощью Anaconda
Зарегистрируйте аккаунт Open ai, а затем получите ключ API ниже.
1
0
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Решение

После долгих поисков и попыток я смог найти решение, которое работает для моей страницы, и объяснил его. Это еще не общее и системное решение, если у кого-то есть другие идеи по его улучшению, не стесняйтесь, в любом случае вот прокомментированный скрипт, который работает системно (на сегодняшний день 01.11.2023).

Запросите Chrome и этот пакет:

pip install selenium chromedriver_binary
  • selenium — это библиотека с открытым исходным кодом, которая позволяет ей работать внутри экземпляра веб-браузера, обычно используемого для отладки и тестирования кода. Здесь используется для извлечения информации из среды браузера.
  • chromedriver_binary — это плагин для управления браузером Chromium.

Чтобы понять код, запомните эту структуру DOM с теневым корнем:

(Ссылка на руководство: https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM)

Код:

from selenium import webdriver
from selenium.webdriver.common.by import By

url = 'https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_namespace_System.htm'

timeout = 10
driver = webdriver.Chrome()  # Open Chromium instance where the code and shadow-root can be processed
driver.implicitly_wait(timeout)  # Set timeout before run command, it give the time at the DOM to self create

driver.get(url)  # Open Chrome page at request url

# The following block of code was written specifically for this case, unfortunately for now it is not a complete and automatic solution.


# With the CSS_SELECTOR (using ID and tag_name) the code travel through the DOM.
shadow_host_1 = driver.find_element(By.CSS_SELECTOR, '#maincontent > doc-xml-content')
shadow_root_1 = shadow_host_1.shadow_root

shadow_host_2 = shadow_root_1.find_element(By.CSS_SELECTOR, 'doc-content')
shadow_root_2 = shadow_host_2.shadow_root

# <-- In the Salesforce Reference manual, all page after this point has all the shadow content in the main div loaded (True today @ 11/01/23)

# Finally reach the target Shadow DOM tree, simply search the correct tag and export the HTML data
element = shadow_root_2.find_element(By.CSS_SELECTOR, 'div.related-links')
elementHTML = element.get_attribute("outerHTML")  # get_attribute("outerHTML") return html Tag + Content
print(elementHTML)
driver.quit()

Это решение не является глобальным, необходимо обрабатывать все теневые корни, и по этой причине важно знать окончательную структуру. Легко сгенерировать этот код с помощью консоли разработчика в Chrome, но я думаю, что решение должно быть более элегантным... Не стесняйтесь разрабатывать более элегантное и мощное решение!

ВАЖНО: Поскольку теневой корень отличается от DOM-TREE, и браузер объединяет его с отцом на этапе рендеринга без «driver.implicitly_wait(timeout)», результат не является детерминированным, поскольку Total DOM не может загрузиться. а 'find_element' не может найти частичную досягаемость после нескольких загрузок».

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