我正在学习如何使用 Selenium Python 与自动建议下拉菜单进行交互。我是一个视障人士,使用开发工具有困难,因为它需要鼠标操作,所以我非常依赖
page_source
来获取相关定位器。
我希望有人能帮我解决问题。
我尝试了以下两种方法来获取城市列表,但仍然无法使用
.click()
或 Keys.ENTER
选择特定城市:
cities = driver.find_elements(By.CLASS_NAME, "ac_cityname")
cities = driver.find_elements(By.XPATH, "//\*\[contains(text(), 'ckland')\]")
提前致谢。
代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
options.add_argument('--ignore-certificate-errors')
options.add_argument('--incognito')
driver = webdriver.Chrome(options=options)
from time import sleep
import clipboard
driver.get('https://www.yatra.com/flights')
driver.maximize_window()
sleep(0.5)
#Copy html code to clipboard
clipboard.copy(driver.page_source)
#Click "I Agree" cookies policy button
try:
driver.find_element_by_xpath("//button[contains(text(), 'I Agree')]").click()
sleep(1)
except NoSuchElementException:
print("No Cookies Agree button!")
#Find "Depart From" edit box
depart_from = WebDriverWait(driver, 20).until(
EC.presence_of_element_located((By.ID, "BE_flight_origin_city")))
sleep(0.5)
depart_from.click()
sleep(0.5)
depart_from.clear()
#input partial city name "Au" : Auckland
depart_from.send_keys('Au')
sleep(0.5)
print("From:", depart_from.get_attribute('value')) # return string entered
sleep(0.5)
print("depart_from enabled:", depart_from.is_enabled()) #Verify
cities = driver.find_elements(By.CLASS_NAME, "ac_cityname")
#I have also tried
#cities = driver.find_elements(By.XPATH, "//*[contains(text(), 'ckland')]")
for city in cities:
print(city.text)
if "Auckland" in city.text:
# I have tries following 2 methods:
city.click()
# and
这是一个很难弄清楚的问题。该网站表现得很奇怪......正常的等待无法正常工作,等等。对于 Selenium 的默认行为来说,这一切都有点“过于动态”。不管怎样,我有一些建议,然后我把工作代码放在底部。
一些建议:
您正在使用非常旧版本的 Selenium,因为您可以使用语法,
.find_element_by_xpath()
。我强烈建议您更新到最新版本。
更新后的语法是
driver.find_element(By.XPATH, "")
driver.find_element(By.CSS_SELECTOR, "")
driver.find_element(By.ID, "")
所以...不同但不是完全不同。请参阅文档了解更多信息。
time.sleep()
是一种不好的做法。这是一个“愚蠢的”等待......如果元素提前准备好,它仍然等待 X 秒。如果您需要等待,请使用 WebDriverWait
代替。您已经在使用它了一些...只需用等待替换所有睡眠即可。您的脚本将更快、更一致可靠。
话虽如此,我确实在这里睡了一些觉,因为适当的等待有时不起作用。我的一般规则是找到一种每次都使用等待的方法。当我没有想法并且无法让
WebDriverWait
工作时,我就会把睡觉作为最后的手段。
当使用
WebDriverWait
或任何可以重复使用的东西时,请将其存储在变量中,以便可以重复使用,例如
wait = WebDriverWait(driver, 10)
depart_from = wait.until(EC.presence_of_element_located((By.ID, "BE_flight_origin_city")))
它可以让您不必花费时间和资源重复重新实例化同一对象等。
在 Selenium 术语中,存在意味着元素存在于 DOM 中,但不是可见或可点击。您通常不应该等待出现。如果您想单击某个元素,请使用
EC.element_to_be_clickable()
等待其可单击。如果您想以其他方式与元素交互,请使用 EC.visibility_of_element_located()
等待可见。
工作代码...
url = 'https://www.yatra.com/flights'
driver = webdriver.Chrome()
driver.maximize_window()
driver.get(url)
wait = WebDriverWait(driver, 10)
# Copy html code to clipboard
clipboard.copy(driver.page_source)
# Click "I Agree" cookies policy button
try:
driver.find_element(By.XPATH, "//button[contains(text(), 'I Agree')]").click()
except NoSuchElementException:
print("No Cookies Agree button!")
# Find "Depart From" edit box
airport_name = 'Auckland'
depart_from = wait.until(EC.element_to_be_clickable((By.ID, "BE_flight_origin_city")))
time.sleep(1)
depart_from.click()
time.sleep(1)
depart_from.send_keys(airport_name)
time.sleep(1)
driver.find_element(By.XPATH, f"//p[@class='ac_cityname'][contains(.,'{airport_name}')]").click()