0

I'm using Selenium to download several files. The process is simple: I look for a reference, wait until results are ready and download the associated files.

I've a problem with the part "wait until results are ready". The website uses an AJAX table which loads the results. During the update of this table, an attribute appears in the HTML code and when results are ready it dissapears.

The object is always present, it's only the attribute that changes. If I do the next loop just right after clicking the button of search:

for i in range(0,10):
    print(self.driver.find_element(By.ID, "gridpoOverview").get_attribute("aria-busy"))
    time.sleep(0.05)

It returns (so I know how to detect it):

none 
true
true
none
none
none
none
none
none
none

I want to do it using an EC, but the next code doesn't work (Timeout exception):

WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, '//div[@id="gridpoOverview" and @aria-busy="true"]')))
Ralk
  • 443
  • 1
  • 6
  • 17
  • Does [this](https://stackoverflow.com/q/43813170/6843158) help ? – Kate Nov 08 '21 at 17:19
  • Actually I've already tested this method. The problem is that the object always exists, it's only the attribute which appears/dissapears – Ralk Nov 08 '21 at 17:35
  • Is this a polling loop? (updating every x units of time?) Or is it just a loading indicator? – pcalkins Nov 08 '21 at 20:29
  • Each 0.05 seconds since I clicked the "Search" button I get the attribute "aria-busy" of the element with ID "gridpoOverview". What we can see it's that, at one moment, it becames "true" (while the results are loading) while the rest of the time it just doesn't exist (that's why it returns "none") – Ralk Nov 08 '21 at 20:41
  • ok, it sounds like it's just a "loading" indicator. You should just use a webdriverwait to get what should show after the loading is done. Be sure to catch stale element exceptions and re-get the webelement if caught. You can use something like this answer: https://stackoverflow.com/questions/66820416/random-errors-using-wait-for-element-clickable-method-in-selenium/66820707#66820707 (Or create a function and try/catch... re-call function if stale element in caught.) The key is that Stale Element will be thrown on a webelement method call if DOM is still updating. – pcalkins Nov 08 '21 at 22:42

2 Answers2

1

Seems you are close enough.

As returned by get_attribute("aria-busy") the value of aria-busy attribute turns True.

So you need to replace true with True as follows:

WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, '//div[@id="gridpoOverview" and @aria-busy="True"]')))

Update

As per your updated question you can use:

WebDriverWait(driver, 10).until(EC.staleness_of(driver.find_element_by_xpath("//div[@id="gridpoOverview" and not(@aria-busy)]")))

Or

WebDriverWait(driver, 10).until(EC.staleness_of(driver.find_element(By.XPATH, "//div[@id="gridpoOverview" and not(@aria-busy)]")))
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
0

I've found a solution that works, but I don't know why.

The attribute 'aria-disabled' from the same element is always present. If I include this line before, it will work.

    WebDriverWait(self.driver, 20).until(EC.element_attribute_to_include((By.XPATH, '//div[@id="gridpoOverview"]'),'aria-disabled'))
    WebDriverWait(self.driver, 20).until(EC.element_attribute_to_include((By.XPATH, '//div[@id="gridpoOverview"]'),'aria-busy'))

If the first line if not present, it does not work (I've the Timeout exception).

Does anyone knows why ?

Ralk
  • 443
  • 1
  • 6
  • 17