Python Selenium 输入框发送按键问题
我刚开始使用Python的Selenium库,想要自动化这个商店的结账流程,网址是https://bellevo.store/products/luna。我已经写了代码,可以点击“立即购买”并填写信息,一切都很顺利,直到要填写城市这一栏。我觉得它没有把城市字段识别为可以点击的,我也不太明白为什么。希望能得到一些帮助。这是我的代码:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
# Initialize a new browser instance
driver = webdriver.Chrome()
# Click "Buy It Now"
wait = WebDriverWait(driver, 10)
buy_now_button = wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id=\"product form-template--22164028883241__main\"]/div/div/dynamic-checkout")))
buy_now_button.click()
# Fill in contact and delivery fields
wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id=\"email\"]"))).send_keys(phone_number)
time.sleep(.5)
wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id=\"TextField0\"]"))).send_keys(first_name)
time.sleep(.5)
wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id=\"TextField1\"]"))).send_keys(last_name)
time.sleep(.5)
wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id=\"billing-address1\"]"))).send_keys(address + ", " + city + ", " + state + ", USA")
time.sleep(.5)
wait.until(EC.element_to_be_clickable((By.XPATH, "//label[@id=\"TextField6-label\"]"))).send_keys(city)
我尝试了很多不同的方法,但还是找不到解决办法。正如我所说,我对Selenium还不太熟悉,可能理解得不够透彻。
1 个回答
你做得很不错,代码写得也很好。我有一些建议可以让它更好。
这个情况可能有点棘手。我觉得你遇到的问题是,你在填写城市字段时,那个字段看不见,因为地址建议的下拉框打开了。有几种方法可以解决这个问题……
- 你可以按照自己的方法,手动填写所有字段(地址、城市、州、邮政编码)。这样的话,你需要先关闭地址建议的下拉框,才能填写城市、州和邮政编码。如果选择这个方法,你只需要把地址填到地址字段里,因为你不使用地址建议下拉框。城市、州和邮政编码就填到各自的字段里。
- 使用自动建议列表,选择第一个选项,这个选项应该和你输入的完整地址匹配。
我选择了第二种方法。我还整理了一些内容……
如果你使用的是ID,建议用
By.ID()
,而不是By.XPATH()
。我去掉了
time.sleep()
。你不需要它们,因为你已经有了合适的等待时间。你使用了WebDriverWait
,这很好……使用它们是最佳实践,避免使用time.sleep()
。将来如果你有嵌套的双引号(
"
),可以用单引号('
)交替使用,比如把"//*[@id=\"email\"]"
改成"//*[@id='email']"
。这样更容易阅读,也去掉了转义字符。如果你要点击一个元素,使用
EC.element_to_be_clickable()
。如果你要与元素进行其他交互,比如发送键值,使用EC.visibility_of_element_located()
。大多数情况下避免使用EC.presence_of_element_located()
……它只是确认元素在DOM中,而不是确认它可见或可以点击。我看到很多人使用这个,然后再去点击元素……这样容易导致一些难以追踪的问题。虽然不是必须的,但我更喜欢用
f
字符串来拼接字符串。我觉得这样更容易阅读和使用。这样就不需要每次插入新变量时都确保引号匹配了。想了解更多,可以查看 文档。s = address + ", " + city + ", " + state + ", USA"
变成
s = f"{address}, {city}, {state}, USA"
考虑到我所有的建议,下面是整理后的代码,并且可以正常工作。
from selenium import webdriver
from selenium.webdriver import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
# Initialize a new browser instance
url = 'https://bellevo.store/products/luna'
driver = webdriver.Chrome()
driver.maximize_window()
driver.get(url)
wait = WebDriverWait(driver, 10)
# Click "Buy It Now"
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"button.shopify-payment-button__button"))).click()
# Fill in contact and delivery fields
wait.until(EC.element_to_be_clickable((By.ID, "email"))).send_keys(phone_number)
wait.until(EC.element_to_be_clickable((By.ID, "TextField0"))).send_keys(first_name)
wait.until(EC.element_to_be_clickable((By.ID, "TextField1"))).send_keys(last_name)
e = wait.until(EC.visibility_of_element_located((By.ID, "billing-address1")))
e.send_keys(f"{address}, {city}, {state}, USA")
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#billing-address1-options > li"))).click()
e.send_keys(Keys.ENTER)