Selenium не может найти все элементы на HTML-странице

Я делаю парсинг на портале недвижимости <www.immobiliare.it>

В частности, я получаю некоторую информацию со страницы поиска, которая содержит 25 свойств на странице. Мне удалось получить почти все, но у меня возникли проблемы с получением src изображения карты, которое есть у каждого свойства. Эта карта находится после селектора CSS.

Структура HTML следующая:

Я смог получить эти данные с помощью селена: https://stackoverflow.com/a/75020969/14461986

from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager

Options = Options()
Options.headless = True

driver = webdriver.Chrome(options=Options, service=Service(ChromeDriverManager().install()))
url = 'https://www.immobiliare.it/vendita-case/milano/forlanini/?criterio=dataModifica&ordine=desc&page=3'
driver.get(url)

soup = BeautifulSoup(driver.page_source)

data = []

# Each property is contained under each li in-realEstateResults__item
for property in soup.select('li.in-realEstateResults__item'):

    data.append({
            'id': property.get('id'),
            'MapUrl': property.select_one('[alt = "mappa"]').get('src') if property.select_one('[alt = "mappa"]') else None
        })

print(data)

Однако после 4-го изображения MapUrl становится пустым. Свойства загружены правильно, так как я проверил идентификаторы, а также HTML для остальных изображений тот же, но по какой-то причине я не понимаю, что MapUrl не извлекается. Я также приветствовал бы любые советы о том, как сделать этот сценарий более эффективным.

Может быть, этот элемент не отображается, а где-то за кадром?

dc914337 09.01.2023 16:39

Вручную вы можете передать изображения и добраться до карты для каждого свойства. Кроме того, проверив html-код в браузере, вы также можете найти каждый из источников карты.

Kaynef21 09.01.2023 16:41
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
2
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Однако проблема здесь заключается в ленивой загрузке, поэтому вам нужно взаимодействовать с веб-сайтом и прокручивать вниз, чтобы принудительно загрузить.

Возможно, вам придется принять/закрыть некоторые всплывающие окна (необязательно):

driver.find_element(By.CSS_SELECTOR,'#didomi-notice-agree-button').click()
driver.find_element(By.CSS_SELECTOR,'.nd-dialogFrame__close').click()
driver.find_element(By.CSS_SELECTOR,'section h1').click()

Теперь мы можем начать прокрутку (простое, но работающее решение, которое можно улучшить):

for i in range(30):
        driver.find_element(By.CSS_SELECTOR,'body').send_keys(Keys.PAGE_DOWN)
        time.sleep(0.3)

Пример

from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))

url = 'https://www.immobiliare.it/vendita-case/milano/forlanini/?criterio=dataModifica&ordine=desc'
driver.get(url)


driver.find_element(By.CSS_SELECTOR,'#didomi-notice-agree-button').click()
driver.find_element(By.CSS_SELECTOR,'.nd-dialogFrame__close').click()
driver.find_element(By.CSS_SELECTOR,'section h1').click()

for i in range(30):
        driver.find_element(By.CSS_SELECTOR,'body').send_keys(Keys.PAGE_DOWN)
        time.sleep(0.3)


soup = BeautifulSoup(driver.page_source)

data = []
for e in soup.select('li.in-realEstateResults__item'):
    data.append({
        'title':e.a.get('title'),
        'imgUrls':[i.get('src') for i in e.select('.nd-list__item img')],
        'imgMapInfo': e.select_one('[alt = "mappa"]').get('src') if e.select_one('[alt = "mappa"]') else None
    })

data

Единственная модификация, которую я бы добавил: эти два после нескольких выполнений (открытие нескольких страниц с одним и тем же драйвером), похоже, терпят неудачу. Если я удалю их, скрипт работает отлично. driver.find_element(By.CSS_SELECTOR,'#didomi-notice-agree-bu‌​tton').click() driver.find_element(By.CSS_SELECTOR,'.nd-dialogFrame__close'‌​).click()

Kaynef21 10.01.2023 09:53

Это правильно, если это выходит за рамки примера и необходимо обрабатывать дальнейшие страницы результатов, я бы проверял наличие элементов и выполнял действия в зависимости от них или проектировал поток таким образом, чтобы они использовались только изначально при вызове и инкапсулировать итерацию страниц.

HedgeHog 10.01.2023 10:24

Для меня скрипт работает без щелчка по этим элементам, поэтому я решил их удалить.

Kaynef21 10.01.2023 11:35

С точки зрения эффективности, есть ли способ ускорить этот процесс? Я только что использовал Options.headless = True для драйвера, но мне нужно было бы сделать его еще легче.

Kaynef21 10.01.2023 12:58

Пока я углублялся в это, я смог найти решение requests и beautifulsoup. Лес за деревьями - я никогда не перестаю учиться. Исправил мой первоначальный подход stackoverflow.com/a/75020969/14461986

HedgeHog 10.01.2023 15:18

Я разработал свой алгоритм на основе вашего ответа (я извлекаю гораздо больше данных), и решение потрясающее. Идет сверхбыстро. Большое спасибо!

Kaynef21 11.01.2023 16:56

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