You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Selenium Python定位马士基网站多层Shadow Root内的输入框

马士基船期查询页输入框交互问题

我用Selenium Python开展网页自动化项目,目标页面为马士基船期查询页(https://www.maersk.com/schedules/pointToPoint)。尝试点击页面上的“From (City, Country/Region)”和“To (City, Country/Region)”输入框时,通过find_elements获取的input元素执行click()方法会抛出ElementNotInteractableException异常。目标输入框位于form标签内,页面还包含iframe元素。


原Python代码

from webdriver_manager.chrome import ChromeDriverManager
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import ImageTk, Image
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import time
import os
import wget
import pandas as pd
import csv
from collections.abc import Iterable
import glob
import shutil
import re
import openpyxl
from selenium import webdriver
from PIL import Image
import pytesseract
from selenium.common.exceptions import TimeoutException

# Automatically download and set up the appropriate ChromeDriver
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get(f"https://www.maersk.com/schedules/pointToPoint")
#time.sleep(1)
driver.maximize_window()


allow_all = WebDriverWait(driver, 
10).until(EC.presence_of_element_located((By.XPATH, "//*[@id='coiPage- 
1']/div[2]/button[3]")))

allow_all.click()

form = driver.find_element(By.CLASS_NAME, "schedules-view__search--box")


# Find the input element within the form

input_element = form.find_elements(By.TAG_NAME, "input")

# Click on the first input element or perform any action needed
print(input_element)

代码输出

[<selenium.webdriver.remote.webelement.WebElement (session="3fb48d1f542b127316d4cb737f238639", element="B037E6D01D955BB15533DAE9CA20FFB4_element_66")>, <selenium.webdriver.remote.webelement.WebElement (session="3fb48d1f542b127316d4cb737f238639", element="B037E6D01D955BB15533DAE9CA20FFB4_element_68")>, <selenium.webdriver.remote.webelement.WebElement (session="3fb48d1f542b127316d4cb737f238639", element="B037E6D01D955BB15533DAE9CA20FFB4_element_70")>, <selenium.webdriver.remote.webelement.WebElement (session="3fb48d1f542b127316d4cb737f238639", element="B037E6D01D955BB15533DAE9CA20FFB4_element_72")>]

报错信息

执行input_element[0].click()时抛出:

ElementNotInteractableException           Traceback (most recent call last)
Cell In[26], line 1
----> 1 input_element[0].click()

File ~\anaconda3\lib\site-packages\selenium\webdriver\remote\webelement.py:93, in WebElement.click(self)
     91 def click(self) -> None:
     92     """Clicks the element."""
---> 93     self._execute(Command.CLICK_ELEMENT)

File ~\anaconda3\lib\site-packages\selenium\webdriver\remote\webelement.py:410, in WebElement._execute(self, command, params)
    408     params = {}
    409 params["id"] = self._id
--> 410 return self._parent.execute(command, params)

File ~\anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py:444, in WebDriver.execute(self, driver_command, params)
    442 response = self.command_executor.execute(driver_command, params)
    443 if response:
--> 444     self.error_handler.check_response(response)
    445     response["value"] = self._unwrap_value(response.get("value", None))
    446     return response

File ~\anaconda3\lib\site-packages\selenium\webdriver\remote\errorhandler.py:249, in ErrorHandler.check_response(self, response)
247         alert_text = value["alert"].get("text")
248     raise exception_class(message, screen, stacktrace, alert_text)  # type: ignore[call-arg]  # mypy is not smart enough here
--> 249 raise exception_class(message, screen, stacktrace)

ElementNotInteractableException: Message: element not interactable
(Session info: chrome=119.0.6045.160)
Stacktrace:
GetHandleVerifier [0x003072A3+45731]
(No symbol) [0x00292D51]
(No symbol) [0x001886D0]
(No symbol) [0x001BCAC4]
(No symbol) [0x001B4FC0]
(No symbol) [0x001D7FDC]
(No symbol) [0x001B4A4E]
(No symbol) [0x001D8254]
(No symbol) [0x001EB7A2]
(No symbol) [0x001D7DD6]
(No symbol) [0x001B31F6]
(No symbol) [0x001B439D]
GetHandleVerifier [0x00610716+3229462]
GetHandleVerifier [0x006584C8+3523784]
GetHandleVerifier [0x0065214C+3498316]
GetHandleVerifier [0x00391680+611968]
(No symbol) [0x0029CCCC]
(No symbol) [0x00298DF8]
(No symbol) [0x00298F1D]
(No symbol) [0x0028B2C7]
BaseThreadInitThunk [0x7548FCC9+25]
RtlGetAppContainerNamedObjectPath [0x770A7C6E+286]
RtlGetAppContainerNamedObjectPath [0x770A7C3E+238]
(No symbol) [0x00000000]

目标输入框所在form标签HTML结构

<form novalidate="" class="schedules-view__search--box">
  <mc-c-origin-destination class="origin-destination"></mc-c-origin-destination>
  <hr class="schedules-view__search--divider">
  <div class="form-group">
    <div class="date-section">
      <mc-select-native id="sortBy" name="sortBy" value="[{&quot;label&quot;:&quot;Departing&quot;,&quot;value&quot;:&quot;D&quot;}]"><input type="text" name="sortBy" style="display:none" aria-hidden="true" tabindex="-1" value="[{&quot;label&quot;:&quot;Departing&quot;,&quot;value&quot;:&quot;D&quot;}]" data-di-id="di-id-a9af2e59-782584d2"></mc-select-native>
      <mc-input-date data-test="ptp-date-picker"
        dontusenativeonmobile="" id="" name="ptpDatePicker" value="23/11/2023"><input type="text" name="ptpDatePicker" style="display:none" aria-hidden="true" tabindex="-1" value="23/11/2023" data-di-id="di-id-d08f07b1-d6f0dde0"></mc-input-date>
    </div>
    <hr class="schedules-view__search--divider">
    <div class="container-section">
      <div class="form-group">
        <mc-select-native id="containerType" name="containerType" value="[{&quot;label&quot;:&quot;40' Dry Standard&quot;,&quot;value&quot;:&quot;42G1&quot;}]"><input type="text" name="containerType" style="display:none" aria-hidden="true" tabindex="-1" value="[{&quot;label&quot;:&quot;40' Dry Standard&quot;,&quot;value&quot;:&quot;42G1&quot;}]" data-di-id="di-id-409271ab-305b2833"></mc-select-native>
        <mc-checkbox
          id="reeferCheckbox"></mc-checkbox>
      </div>
    </div>
  </div>
  <hr class="schedules-view__search--divider">
  <div class="form-group vessel-flag">
    <mc-c-typeahead clearbutton="" id="vesselFlag" name="vesselFlag" value=""><input type="text" name="vesselFlag" style="display:none" aria-hidden="true" tabindex="-1" value="" data-di-id="di-id-f906762b-b9bc3f2e"></mc-c-typeahead>
  </div>
  <div class="form-group">
    <mc-button data-test="ptp-search-button" fit="medium" appearance="primary" variant="filled" width="full-width">Search</mc-button>
  </div>
</form>

解决方案及代码示例

问题原因

  1. 你定位到的input元素是隐藏元素(HTML中含style="display:none"),这类元素不可交互,并非页面上实际显示的输入框。
  2. 实际可交互的输入框在自定义组件<mc-c-origin-destination>内部,需定位该组件下的可见输入区域。
  3. 页面存在动态加载,需等待元素完全可交互后再操作。

优化后的代码

from webdriver_manager.chrome import ChromeDriverManager
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 初始化浏览器
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get("https://www.maersk.com/schedules/pointToPoint")
driver.maximize_window()

# 处理Cookie弹窗,等待元素可点击后操作
WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.XPATH, "//*[@id='coiPage-1']/div[2]/button[3]"))
).click()

# 等待出发地输入框可交互并输入内容
from_input = WebDriverWait(driver, 15).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "mc-c-origin-destination .origin input"))
)
from_input.click()
from_input.send_keys("Shanghai, China")

# 等待目的地输入框可交互并输入内容
to_input = WebDriverWait(driver, 15).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "mc-c-origin-destination .destination input"))
)
to_input.click()
to_input.send_keys("Los Angeles, USA")

关键说明

  • 定位正确元素:通过CSS选择器直接定位<mc-c-origin-destination>下的.origin input和.destination input,这些是页面可见的可交互输入框。
  • 使用显式等待:用element_to_be_clickable替代presence_of_element_located,确保元素加载完成且可操作,避免静态等待time.sleep()的不可靠性。
  • iframe处理(若需):如果后续发现输入框位于iframe内,需先切换到iframe再操作,示例代码:
    # 切换到目标iframe(需替换为实际iframe的定位符)
    WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "target_iframe_id")))
    # 操作输入框...
    # 操作完成后切回主文档
    driver.switch_to.default_content()
    

内容的提问来源于stack exchange,提问作者Santhosh Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 18:47:02