selenium python通过内部文本单击a href

selenium python通过内部文本单击a href,python,selenium,Python,Selenium,我试图在一些自动化测试网站上以编程方式切换国家,每个国家的价格都不一样,所以我正在编程一个小工具来帮助我决定从哪里购买 首先,我通过以下操作将所有货币放入列表: def get_all_countries(): one = WebDriverWait(driver1, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "selected-currency"))) one.click() el = WebDriverW

我试图在一些自动化测试网站上以编程方式切换国家,每个国家的价格都不一样,所以我正在编程一个小工具来帮助我决定从哪里购买

首先,我通过以下操作将所有货币放入列表:

def get_all_countries():
    one = WebDriverWait(driver1, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "selected-currency")))
    one.click()
    el = WebDriverWait(driver1, 10).until(EC.visibility_of_element_located((By.CLASS_NAME, "site-selector-list")))
    list_return = []
    a_tags = el.find_elements_by_tag_name('a')
    for a in a_tags:
        list_return.append(a.text)
    return list_return
例如,它返回:
[‘英国’、‘美国’、‘法国’、‘德国’、‘埃斯帕尼亚’、‘澳大利亚’、‘П砦砦砦砦砦’]
,然后,我遍历列表,每次调用此函数时:

def set_country(text):
    is_change_currency_displayed = driver1.find_element_by_id("siteSelectorList").is_displayed()
    if not is_change_currency_displayed:  # get_all_countries function leaves dropdown open. Check if it is open before clicking it.
        one = WebDriverWait(driver1, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "selected-currency")))
        one.click()
    div = WebDriverWait(driver1, 10).until(EC.visibility_of_element_located((By.CLASS_NAME, "site-selector-list")))
    a_tags = div.find_elements_by_tag_name('a')
    for a in a_tags:
        try:
            if a.text == text:
                driver1.get(a.get_attribute("href"))
        except StaleElementReferenceException:
            set_country(text)
当比较a.text和text时,我得到了一个StaleElementReferenceException,我在网上读到它意味着对象从我保存它时起发生了更改,一个简单的解决方案是再次调用该函数。但是,我不太喜欢这个解决方案和这段代码,我认为这是无效的,需要太多的时间,有什么想法吗

编辑:

def main(url):
    driver1.get(url)
    to_return_string = ''
    one = WebDriverWait(driver1, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "selected-currency")))
    one.click()
    el = WebDriverWait(driver1, 10).until(EC.visibility_of_element_located((By.CLASS_NAME, "site-selector-list")))
    a_tags = el.find_elements_by_tag_name('a')
    for a in a_tags:
        atext = a.text
        ahref = a.get_attribute('href')
        try:
            is_change_currency_displayed = driver1.find_element_by_id("siteSelectorList").is_displayed()
            if not is_change_currency_displayed:  # get_all_countries function leaves dropdown open.
                one = WebDriverWait(driver1, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "selected-currency")))
                one.click()
            driver1.get(ahref)
            current_price = WebDriverWait(driver1, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, ".current-price")))
            to_return_string += ("In " + atext + " : " + current_price.text + ' \n')
            print("In", atext, ":", current_price.text)
        except TimeoutException:
            print("In", atext, ":", "Timed out waiting for page to load")
            to_return_string += ("In " + atext + " : " + " Timed out waiting for page to load" + ' \n')
    return to_return_string


main('http://us.asos.com/asos//prd/7011279')

如果过时元素是
a
标记而不是
div
,则可以迭代a标记的长度,并通过
div
获取每个元素的文本:

for i in range(len(div.find_elements_by_tag_name('a')):
    if div.find_elements_by_tag_name('a')[i].text == text:
        driver1.get(div.find_elements_by_tag_name('a')[i].get_attribute("href"))
这样,您就可以从DOM中删除最新的元素


如果过时的元素是
div
,则需要验证该下拉列表在
one之后是否消失。单击()
,将其悬停或以其他方式

另一种方法是将
a.text
更改为等待:

wait = WebDriverWait(driver, 10, poll_frequency=1, ignored_exceptions=[StaleElementReferenceException])
a = wait.until(EC.text_to_be_present_in_element((By.YourBy)))

如果我正确理解问题陈述,添加
break
陈述可以解决问题:

def set_country(text):
    is_change_currency_displayed = driver1.find_element_by_id("siteSelectorList").is_displayed()
    if not is_change_currency_displayed:  # get_all_countries function leaves dropdown open. Check if it is open before clicking it.
        one = WebDriverWait(driver1, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "selected-currency")))
        one.click()
    div = WebDriverWait(driver1, 10).until(EC.visibility_of_element_located((By.CLASS_NAME, "site-selector-list")))
    a_tags = div.find_elements_by_tag_name('a')
    for a in a_tags:
        try:
            if a.text == text:
                driver1.get(a.get_attribute("href"))
                break
        except StaleElementReferenceException:
            set_country(text)

DOM
更新一次
驱动程序。调用get
。因此,与旧页面相关的引用(即a_标记)将不起作用


相反,
您应该打破循环
并在使用
驱动程序检索到给定的国家/地区页面后立即出来。满足条件后获取
。因此,您设置了所需的国家/地区,无需反复检查是否存在条件,这显然会导致
StaleElementReferenceException

谢谢,我稍后在靠近计算机时会尝试,另一个问题是,你认为首先获取国家列表是一件好事吗?还是有一个主要功能可以遍历国家的长度,每次单击不同的国家并获取价格?我尝试了选项一,如果过时的元素是a,它仍然不起作用,那么我想它是div,但是,我还不明白你的解决方案。让我们试着澄清一下这个场景:首先你说它是用于自动化测试的,但是从描述中我看到你试图从一个叫做“抓取”的网站上自动获取信息,这需要一种不同的方法,对吗?如果是这样的话,更好的选择是在一个主函数中迭代,每次单击货币,而不是首先获取列表,因为它可能会导致过时的元素。我建议的另一件事是在浏览器打开的情况下逐行运行调试,以查看发生了什么,并了解异常的确切原因。好的,那么你是对的,我认为你试图用selenium做的任何事情都是自动化测试,我正在尝试进行刮片。无论如何,我将代码更新为一个主函数,现在StaleElementReferenceException在这一行:atext=a.text。我还尝试更改代码,并且每次都再次获取a引用,因此我不会得到此错误,但我失败了。您在每次发送driver.get if a.text=text条件时都在更改网页。因此,在调用driver.get后,当DOM更新时,原始页面将丢失。