使用Selenium和Python,通过链接文本点击a href。

3
我是一个有用的助手,可以为您翻译文本。
我正在尝试在网站上进行一些自动化测试,并以编程方式切换国家。由于每个国家的价格不同,因此我正在编写一个小工具来帮助我决定从哪里购买。
首先,我通过执行以下操作将所有货币存入列表中:
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

例如,它返回:['United Kingdom', 'United States', 'France', 'Deutschland', 'España', 'Australia', 'Россия'],然后我遍历列表并每次调用此函数:
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')

每次在“if a.text = text”条件下发送“driver.get”时,您都会更改网页。因此,一旦调用“driver.get”,原始页面就会丢失,因为DOM已更新。 - Naveen Kumar R B
2个回答

2
如果我正确理解了问题陈述,添加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 一旦调用 driver.get 就会被更新。因此,与旧页面相关的引用(例如 a_tags)将无法使用。

相反,应该在满足条件后使用 driver.get 来检索给定国家页面,并中断循环。这样,您设置所需的国家后,就不需要一遍又一遍地进行迭代以检查条件,这显然会导致 StaleElementReferenceException


0

谢谢,我等到回到电脑旁再尝试。另一个问题是,您认为首先获取国家列表是个好主意,还是有一个主函数迭代国家列表长度,每次点击不同的国家并获取价格? - DAVIDBALAS1
我尝试了选项一,如果过时的元素是a,并且仍然无法工作,所以我猜是div的问题,但是我还没有理解你的解决方案。 - DAVIDBALAS1
让我们尝试澄清一下情况:首先,您说这是用于自动化测试,但从描述中我看到您正在尝试自动从一个名为“scraping”的网站获取信息,这需要不同的方法,我对吗?如果是这样,您更好的选择将是在一个主函数中迭代,并每次单击货币,而不是首先获取列表,因为它可能会导致过时的元素。另一件事我建议是逐行在打开浏览器的调试模式下运行,以查看发生了什么并了解导致异常的确切原因。 - Moshisho
好的,你是对的,我以为你用selenium做的任何事情都是自动化测试,而我正在尝试进行爬虫。无论如何,我将代码更新为一个主函数,现在StaleElementReferenceException异常出现在这一行:atext = a.text。我也尝试更改代码,并且每次重新获取a引用,以便不会出现此错误,但我失败了。 - DAVIDBALAS1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接