Search code examples
pythonseleniumbuttonclickrefresh

Selenium Click JS Button - Python?


yeah, there are similar question, but upon reading through them I weren't able to find a solution for my problem.

Following situation: I'm tryin to click the "reply" button on "https://charleston.craigslist.org/ctd/d/charleston-2018-nissan-sentra-sedan-4d/7108660907.html" and after executing this click a popups shows up where I shall click another button, but let's start with the first button as the "reply" click itself is very trouble-making.

The reply button has the following X-Path:

'/html/body/section/section/header/div[2]/div/button'

speaking of which the source code is:

<button role="button" class="reply-button js-only" data-href="/__SERVICE_ID__/chs/ctd/7108660907">
      reply
    </button> 

(see code on mentioned website).

However, my approach with Selenium (Python) doesn't work:

reply_button = '/html/body/section/section/header/div[2]/div/button'
driver.get('https://charleston.craigslist.org/ctd/d/charleston-2018-nissan-sentra-sedan-4d/7108660907.html')

driver.find_element_by_xpath(reply_button).click()

Everytime I tried, the website just loads up properly (even with implementing time.sleep(x)) and tries to click the button, but this fails and the website just refreshes - my guess is that they either regocnize the browser being Selenium-controlled, that the click isn't legitimate or that I didn't catch anything right in my code.. Anyone able to help out?

Btw I already tried searching "by_class_name", that didn't work either.


Solution

  • This Xpath: '/html/body/section/section/header/div[2]/div/button' is like when you get a map with instructions like step forward until you see a car then turn left 30° then step forward until you see a tree then hop twice then go to the second house to your right. Not safe to use, avoid such paths. If the page layout changes, your path may become invalid.

    Try this:

    button = driver.find_element_by_xpath('//*[@class="reply-button js-only"]')
    button.click()
    

    Clicking the button opens a "show phone number" popup (which may be located by driver.find_element_by_xpath('//*[@class="show-phone"]')).

    Explanation:

    If you want proper Xpath, inspect what you want to interact with. The button you want to click is this:

    <button role="button" class="reply-button js-only" data-href="/__SERVICE_ID__/chs/ctd/7108660907">
          reply
        </button>
    

    You can see that it has no "id" tag but it is a button with a specific class. You may copy right away the "class" part -> class="reply-button js-only"

    Now you can check if is it unique enough:

    driver.find_elements_by_xpath('//*[@class="reply-button js-only"]')
    

    If "find elements" returns a single result, usually you should be OK. You can see that all I did is that I pasted the class inside this: driver.find_elements_by_xpath('//*[@ and this ]').

    If you need more accuracy, you can specify that it is a button:

    driver.find_element_by_xpath('//button[@class="reply-button js-only"]')
    

    Or it is the direct child of the element with class: class="actions-combo", so a more safe path would be:

    driver.find_element_by_xpath('//*[@class="actions-combo"]/button[@class="reply-button js-only"]')
    

    This pattern works for all webelement attributes, not just for classes. You could use the role="button" too for more filtering. Look up for Xpath, it is a pretty neat stuff.