由于 <span>(Python - Selenium),无法从动态下拉菜单中抓取输入

Cannot scrape input from dynamic dropdown menu due to <span> (Python - Selenium)

这是一个有点讨论的问题,但是我在其他帖子中没有找到解决方案。

我在 Python 上使用 Selenium 为这个网站创建一个提交包裹的自动化: https://www.mondospedizioni.com

对于 select 国家和城市,我需要在文本字段中添加输入。 文本字段实际上是一个搜索字段,在添加键后会打开一个下拉菜单。

我无法select选项并关闭下拉菜单,因此填写“国家/地区”/“城市”字段并向前移动。

我指的div(国家):

<span class="select2-selection__rendered" id="select2-nazione_mittente-container" title="Selezionare Nazione di ritiro">Selezionare Nazione di ritiro</span>

城市:

<span class="select2-selection__placeholder">Inserire il CAP e selezionare la località</span>

使用 Select,但由于标签我收到错误:

Select only works on <select> elements, not on <span>.

我在 from Anzel 中找到了另一个建议,但即使这个建议也不适合我。

当我尝试输入发件人的城市时,我的代码卡住了,当代码调用收件人国家/地区的输入字段时出现错误。我的代码:

import pandas as pd
import numpy as np
import time
from datetime import datetime, date

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys

import itertools

driver = webdriver.Chrome(executable_path...)
url = "https://www.mondospedizioni.com/"
driver.get(url)
driver.set_page_load_timeout(-1) #Makes sure the webpage is fully loaded before scraping. Thus avoiding errors.

#All Page Components
hoCapito =driver.find_element(By.XPATH, '//*[@id="cookie-bar"]/p/a[1]')

countryFrom = driver.find_element(By.XPATH, '//*[@id="select2-nazione_mittente-container"]')
cityFrom = driver.find_element(By.XPATH, '//*[@id="loc_mittente"]')
postFrom = driver.find_element(By.XPATH, '//*[@id="cap_mittente"]')

countryTo = driver.find_element(By.XPATH, '//*[@id="select2-nazione_destinatario-container"]')
cityTo = driver.find_element(By.XPATH, '//*[@id="loc_destinatario"]')
postTo = driver.find_element(By.XPATH, '//*[@id="cap_destinatario"]')

myWeight = driver.find_element(By.XPATH, '//*[@id="peso1"]')
myLength = driver.find_element(By.XPATH, '//*[@id="l1"]')
myWidth = driver.find_element(By.XPATH, '//*[@id="p1"]')
myHeight = driver.find_element(By.XPATH, '//*[@id="h1"]')

calculate = driver.find_element(By.XPATH, '//*[@id="btn-calcola"]')


#MyKeys
driver = webdriver.Chrome(executable_path=r"C:\Users\AndreaPaviglianiti\Jupyter-2022\webdrivers\chromedriver.exe")
url = "https://www.mondospedizioni.com/"
driver.get(url)
driver.set_page_load_timeout(-1) #Makes sure the webpage is fully loaded before scraping. Thus avoiding errors.

hoCapito =driver.find_element(By.XPATH, '//*[@id="cookie-bar"]/p/a[1]')

countryFrom = driver.find_element(By.XPATH, '//*[@id="select2-nazione_mittente-container"]')
cityFrom = driver.find_element(By.XPATH, '//*[@id="select2-loc_cap_mittente-container"]/span')
postFrom = driver.find_element(By.XPATH, '//*[@id="cap_mittente"]')

countryTo = driver.find_element(By.XPATH, '//*[@id="select2-nazione_destinatario-container"]')
cityTo = driver.find_element(By.XPATH, '//*[@id="loc_destinatario"]')
postTo = driver.find_element(By.XPATH, '//*[@id="cap_destinatario"]')

#Accept Cookies
hoCapito.click()


countryFrom.click()
select_countryFrom = driver.find_element(By.CLASS_NAME, 'select2-search__field').send_keys('Italia')
confirm_countryFrom = driver.find_element(By.XPATH, '//*[@id="select2-nazione_mittente-results"]').click()

cityFrom.click()
select_cityFrom = driver.find_element(By.CLASS_NAME, 'select2-search__field').send_keys('Partinico')
confirm_cityFrom = driver.find_element(By.XPATH, '//*[@id="select2-loc_cap_mittente-results"]/li/div').click()


countryTo.click()
select_countryTo = driver.find_element(By.CLASS_NAME, 'select2-search_field').send_keys('Repubblica Slovacca')
confirm_countryTo = driver.find_element(By.XPATH, '//*[@id="select2-nazione_destinatario-result-885w-Repubblica Slovacca"]').click()

cityTo.send_keys('Bratislava')
postFrom.send_keys(82101)

myWeight.send_keys(30)
myLength.send_keys(47)
myWidth.send_keys(25)
myHeight.send_keys(38)

calculate.click()
time.sleep(3)
driver.set_page_load_timeout(-1)

我的错误(现在 - 基于我最近的尝试):

<ipython-input-77-dd29b60fadf7>:2: DeprecationWarning: executable_path has been deprecated, please pass in a Service object
  driver = webdriver.Chrome(executable_path=r"C:\Users\AndreaPaviglianiti\Jupyter-2022\webdrivers\chromedriver.exe")

---------------------------------------------------------------------------
NoSuchElementException                    Traceback (most recent call last)
<ipython-input-77-dd29b60fadf7> in <module>
     25 cityFrom.click()
     26 select_cityFrom = driver.find_element(By.CLASS_NAME, 'select2-search__field').send_keys('Partinico')
---> 27 confirm_cityFrom = driver.find_element(By.XPATH, '//*[@id="select2-loc_cap_mittente-results"]/li/div').click()
     28 #confirm_cityFrom = driver.find_element(By.XPATH, '//*[@id="select2-loc_cap_mittente-results"]/li/div/text()').click()
     29 #confirm_cityFrom = driver.find_element(By.XPATH, '/html/body/span/span/span[2]').click()

~\Miniconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py in find_element(self, by, value)
   1242             value = '[name="%s"]' % value
   1243 
-> 1244         return self.execute(Command.FIND_ELEMENT, {
   1245             'using': by,
   1246             'value': value})['value']

~\Miniconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py in execute(self, driver_command, params)
    422         response = self.command_executor.execute(driver_command, params)
    423         if response:
--> 424             self.error_handler.check_response(response)
    425             response['value'] = self._unwrap_value(
    426                 response.get('value', None))

~\Miniconda3\lib\site-packages\selenium\webdriver\remote\errorhandler.py in check_response(self, response)
    245                 alert_text = value['alert'].get('text')
    246             raise exception_class(message, screen, stacktrace, alert_text)  # type: ignore[call-arg]  # mypy is not smart enough here
--> 247         raise exception_class(message, screen, stacktrace)
    248 
    249     def _value_or_default(self, obj: Mapping[_KT, _VT], key: _KT, default: _VT) -> _VT:

NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id="select2-loc_cap_mittente-results"]/li/div"}
  (Session info: chrome=98.0.4758.81)
Stacktrace:
Backtrace:
    Ordinal0 [0x007F7AC3+2587331]
    Ordinal0 [0x0078ADD1+2141649]
    Ordinal0 [0x00683BB8+1063864]
    Ordinal0 [0x006B01CE+1245646]
    Ordinal0 [0x006B03CB+1246155]
    Ordinal0 [0x006DA612+1418770]
    Ordinal0 [0x006C86D4+1345236]
    Ordinal0 [0x006D8A0A+1411594]
    Ordinal0 [0x006C84A6+1344678]
    Ordinal0 [0x006A53F6+1201142]
    Ordinal0 [0x006A62E6+1204966]
    GetHandleVerifier [0x0099DF22+1680738]
    GetHandleVerifier [0x00A50DBC+2413564]
    GetHandleVerifier [0x0088D151+563089]
    GetHandleVerifier [0x0088BF13+558419]
    Ordinal0 [0x0079081E+2164766]
    Ordinal0 [0x00795508+2184456]
    Ordinal0 [0x00795650+2184784]
    Ordinal0 [0x0079F5BC+2225596]
    BaseThreadInitThunk [0x77CDFA29+25]
    RtlGetAppContainerNamedObjectPath [0x77E27A9E+286]
    RtlGetAppContainerNamedObjectPath [0x77E27A6E+238]

编辑 为了澄清这个问题,我现在添加了两个打印屏幕,它们专注于我无法管理的元素 - 发件人的位置。

它比我习惯的更先进(而且我对 Selenium 还很陌生)。

#select2-nazione_mittente-container

只需点击上面的元素

.select2-search__field

将密钥发送到上述元素

//li[@class='select2-results__option' and contains(@id,'Italia')]

然后继续单击具有该值的 li 标签。

这是处理任何非 Select 下拉元素的方法。

事实证明,实际上我需要定位并且只有在下拉菜单中只有一个选项时才有效。

我想到了这个解决方案并且它有效,因为我能够完成表单的自动化:

#Sender's City
cityFrom = driver.find_element(By.XPATH, '//*[@id="select2-loc_cap_mittente-container"]').click()
select_cityFrom = driver.find_element(By.XPATH, '/html/body/span/span/span[1]/input').send_keys('Partanna')
time.sleep(1)
confirm_cityFrom = driver.find_element(By.XPATH, '//*[@id="select2-loc_cap_mittente-results"]/li/div').click()