【问题标题】:Can I make Selenium wait for completion of Xhr requests我可以让 Selenium 等待 Xhr 请求的完成吗
【发布时间】:2015-10-27 07:36:33
【问题描述】:

我正在尝试为众多车辆收集定价数据,例如: http://www.leasingcar.dk/privatleasing/Citro%C3%ABn-C1/VTi-68-Feel

我正在迭代选择框“leasingPeriod”,然后是“annualMileage”。

我的问题是,当请求返回时,我已经抓取了数据,所以我每次都检索到相同的价格。我尝试使用隐式等待,但似乎没有任何效果?我也尝试过等待 ajax 调用完成,但无济于事。

我的代码如下所示:

enter code# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.support.select import Select
from selenium.common.exceptions import StaleElementReferenceException, WebDriverException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import unittest

class DataTest(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.driver.get("http://www.leasingcar.dk/privatleasing")

    def testData(self):
        driver = self.driver

        vehicleLinksList = []

        vehicleLinks =driver.find_elements_by_css_selector('div.vehicle[data-nice_url]')
        for linkElement in vehicleLinks:
            vehicleLinksList.append(linkElement.get_attribute("data-nice_url"))

        for link in vehicleLinksList:
        fullUrl = ""
        fullUrl = "http://www.leasingcar.dk" + str(link)
        driver.get(fullUrl)

        leasingPeriodElements = driver.find_element_by_css_selector("select[id=leasingPeriod]")  #get the select element
        periodsOptions = leasingPeriodElements.find_elements_by_tag_name("option") #get all the options into a list

        mileageElements = driver.find_element_by_css_selector("select[id=annualMileage]")  #get the select element
        mileageOptions = mileageElements.find_elements_by_tag_name("option") #get all the options into a list

        periodOptionsList = []
        mileageOptionList = []

            for option in periodsOptions:
                periodOptionsList.append(option.get_attribute("value"))

            for option in mileageOptions: 
                mileageOptionList.append(option.get_attribute("value"))

            for optionValue in periodOptionsList:
                print "starting loop on option %s" % optionValue
                leasingPeriodElement = Select(driver.find_element_by_css_selector("select[id=leasingPeriod]"))
                leasingPeriodElement.select_by_value(optionValue)

                for mileageValue in mileageOptionList:

                    mileageElement = Select(driver.find_element_by_css_selector("select[id=annualMileage]"))
                    mileageElement.select_by_value(mileageValue)

                    #driver.implicitly_wait(10)
                    #WebDriverWait(driver, 10).until(ajax_complete,  "Timeout waiting for page to load")

                    wait = WebDriverWait(driver, 10)
                    price = wait.until(wait_for_visible_element_text_to_contain((By.CSS_SELECTOR, "span.total-price"), "Kr."))

                    print price.text

                   #driver.refresh()
                   #driver.implicitly_wait(10)

def tearDown(self):
        self.driver.quit()


if __name__ == '__main__':
    unittest.main()


class wait_for_visible_element_text_to_contain(object):
    def __init__(self, locator, text):
        self.locator = locator
        self.text = text

    def __call__(self, driver):
        try:
            elements = EC._find_elements(driver, self.locator)
            for element in elements:
                if self.text in element.text and element.is_displayed():
                    return element
        except StaleElementReferenceException:
            return False

def ajax_complete(driver):
    try:
        return 0 == driver.execute_script("return jQuery.active")
    except WebDriverException:
        pass

有什么方法可以检查请求是否已经完成,或者某个值是否已经被刷新?

【问题讨论】:

    标签: python selenium xmlhttprequest


    【解决方案1】:

    弗兰克,

    使用explicit wait 确定数据表中“租赁期”何时更改。比如:

    from selenium.webdriver.support.ui import WebDriverWait
    
    xpath = "//div[@class='data-last']/span[@class='period']"
    
    for elm in driver.find_elements_by_xpath(xpath):
        if elm.is_displayed():
            WebDriverWait(driver, 10).until(
                lambda _: elm.text == "48"
            )
    

    注意:我必须使用 find_elements_by_xpath 并检查元素是否显示,因为存在具有相同 xpath 的隐藏元素。

    【讨论】:

    • 感谢您的回复。我认为我说得不够清楚。我的问题是,当年里程从 15,000 公里变为 20,000 公里并发送新价格请求时,我会在返回新价格之前抓取数据。我需要以某种方式延迟该过程,直到我确定页面数据已刷新?
    • 你会为里程做同样的事情。当您调整选择框时,只需等待里程指示器的值通过使用 WebDriverWait.until 更改并查找调整后的值。 Selenium 的目的是不让您看到系统的后端以及正在发生的事情。它是为用户验收测试而设计的。用户不会知道/关心发生了 AJAX 请求,只是他们正在寻找的值发生了变化。
    猜你喜欢
    • 2018-11-28
    • 2021-01-04
    • 1970-01-01
    • 1970-01-01
    • 2018-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多