L.S
L.S

Reputation: 183

Selenium python : Locate and click on <li> from <a>'s text inside <ul>

I'm a bit stuck in this, I'm trying to click on a specific li in a form.

However this selection is based on the a's text/title which is inside, I try few things but none of them works and I'm interested to understand where is my fault and how to do it better.

This form is powered by Angular and let me select the correct Zip code with city name (great for human, awful for scraping haha). Because I will have to select the correct one by comparison with the current zip code have and the multiple cities which can be linked to one zip code. (If it's not clear, here in France one zip code can have multiple cities, so I have to select the right one).

I used .send_keys() in the element to get the result to be generated (my code is below the example)

Here is an ul example I get :

<ul class="dropdown-menu ng-isolate-scope" ng-show="isOpen() &amp;&amp; !moveInProgress" ng-style="{top: position().top+'px', left: position().left+'px'}" role="listbox" aria-hidden="false" uib-typeahead-popup="" id="typeahead-45-3695" matches="matches" active="activeIdx" select="select(activeIdx, evt)" move-in-progress="moveInProgress" query="query" position="position" assign-is-open="assignIsOpen(isOpen)" debounce="debounceUpdate" style="top: 34px; left: 15px;">
    <!-- ngRepeat: match in matches track by $index --><li class="uib-typeahead-match ng-scope active" ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index, $event)" role="option" id="typeahead-45-3695-option-0" tabindex="0" style="">
        <a href="" tabindex="-1" ng-bind-html="match.label | uibTypeaheadHighlight:query" ng-attr-title="{{match.label}}" class="ng-binding ng-scope" title="56400 - AURAY"><strong>56400</strong> - AURAY</a>
    </li><!-- end ngRepeat: match in matches track by $index --><li class="uib-typeahead-match ng-scope" ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index, $event)" role="option" id="typeahead-45-3695-option-1" tabindex="0" style="">
        <a href="" tabindex="-1" ng-bind-html="match.label | uibTypeaheadHighlight:query" ng-attr-title="{{match.label}}" class="ng-binding ng-scope" title="56400 - PLOUGOUMELEN"><strong>56400</strong> - PLOUGOUMELEN</a>
    </li><!-- end ngRepeat: match in matches track by $index --><li class="uib-typeahead-match ng-scope" ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index, $event)" role="option" id="typeahead-45-3695-option-2" tabindex="0" style="">
        <a href="" tabindex="-1" ng-bind-html="match.label | uibTypeaheadHighlight:query" ng-attr-title="{{match.label}}" class="ng-binding ng-scope" title="56400 - BONO"><strong>56400</strong> - BONO</a>
    </li><!-- end ngRepeat: match in matches track by $index --><li class="uib-typeahead-match ng-scope" ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index, $event)" role="option" id="typeahead-45-3695-option-3" tabindex="0" style="">
        <a href="" tabindex="-1" ng-bind-html="match.label | uibTypeaheadHighlight:query" ng-attr-title="{{match.label}}" class="ng-binding ng-scope" title="56400 - PLOEMEL"><strong>56400</strong> - PLOEMEL</a>
    </li><!-- end ngRepeat: match in matches track by $index --><li class="uib-typeahead-match ng-scope" ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index, $event)" role="option" id="typeahead-45-3695-option-4" tabindex="0">
        <a href="" tabindex="-1" ng-bind-html="match.label | uibTypeaheadHighlight:query" ng-attr-title="{{match.label}}" class="ng-binding ng-scope" title="56400 - BRECH"><strong>56400</strong> - BRECH</a>
    </li><!-- end ngRepeat: match in matches track by $index --><li class="uib-typeahead-match ng-scope" ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index, $event)" role="option" id="typeahead-45-3695-option-5" tabindex="0">
        <a href="" tabindex="-1" ng-bind-html="match.label | uibTypeaheadHighlight:query" ng-attr-title="{{match.label}}" class="ng-binding ng-scope" title="56400 - PLUMERGAT"><strong>56400</strong> - PLUMERGAT</a>
    </li><!-- end ngRepeat: match in matches track by $index --><li class="uib-typeahead-match ng-scope" ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index, $event)" role="option" id="typeahead-45-3695-option-6" tabindex="0">
        <a href="" tabindex="-1" ng-bind-html="match.label | uibTypeaheadHighlight:query" ng-attr-title="{{match.label}}" class="ng-binding ng-scope" title="56400 - PLUNERET"><strong>56400</strong> - PLUNERET</a>
    </li><!-- end ngRepeat: match in matches track by $index --><li class="uib-typeahead-match ng-scope" ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index, $event)" role="option" id="typeahead-45-3695-option-7" tabindex="0">
        <a href="" tabindex="-1" ng-bind-html="match.label | uibTypeaheadHighlight:query" ng-attr-title="{{match.label}}" class="ng-binding ng-scope" title="56400 - SAINTE-ANNE-D'AURAY"><strong>56400</strong> - SAINTE-ANNE-D'AURAY</a>
    </li><!-- end ngRepeat: match in matches track by $index -->
</ul>

Screenshot to see the code in the current situation

So I'm looking to get the title="56400 - AURAY", to check if I'm correct and to click it.

the code I tried mainly :

driver.find_element_by_name("postalCode").send_keys("56400")

ps = driver.find_element_by_css_selector("ul[ng-show=\"isOpen() && !moveInProgress\"]")
for li_p in ps.find_elements_by_css_selector("li[ng-click=\"selectMatch($index, $event)\"]"):
    if li_p.text == '56400 - AURAY':
        li_p.click() 
        break

and

driver.find_element_by_xpath(f"//ul[@ng-show=\"isOpen() && !moveInProgress\" and starts-with(@id, 'li_'][contains(text(),'56400 - AURAY')]").click()

I'm currently doesn't check which one li is correct, I only try to select the correct one with the current correct title

If you have any idea ...

Thank's everyone!

Upvotes: 1

Views: 545

Answers (1)

JaSON
JaSON

Reputation: 4869

You can try to wait for required option in list:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver.find_element_by_name("postalCode").send_keys("56400")
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.LINK_TEXT, '56400 - AURAY'))).click()

Upvotes: 1

Related Questions