1

I want to send a message to this webpage with Python.

It is to say to do the following but with Python:

introducir la descripción de la imagen aquí

That's why I tried the following script with Selenium:

#!/usr/bin/env python3

from selenium import webdriver


api_location = 'http://iphoneapp.spareroom.co.uk'
api_search_endpoint = 'flatshares'
api_details_endpoint = 'flatshares'

location = 'http://www.spareroom.co.uk'
details_endpoint = 'flatshare/flatshare_detail.pl?flatshare_id='

def contact_room(room_id):
    url = '{location}/{endpoint}/{id}?format=json'.format(location=api_location, endpoint=api_details_endpoint, id=room_id)
    print(url)
    driver_path = 'C:\Program Files\chromedriver'
    driver = webdriver.Chrome(executable_path = driver_path )  # Optional argument, if not specified will search path.
    # Go to your page url
    driver.get(url)
    # Get button you are going to click by its id ( also you could use find_element_by_css_selector to get element by css selector)
    button_element = driver.find_element_by_class_name('button button--wide')
    button_element.click()

But it returns:

contact_room(14110387)

(roo_env) (base) C:\Users\antoi\Documents\Programming\roomfinder>python test_message.py
http://iphoneapp.spareroom.co.uk/flatshares/14110387

DevTools listening on ws://127.0.0.1:51038/devtools/browser/401513e8-f221-47f1-ba6b-a7b7f598d839
Traceback (most recent call last):
  File "test_message.py", line 24, in <module>
    contact_room(14110387)
  File "test_message.py", line 21, in contact_room
    button_element = driver.find_element_by_class_name('button button--wide')
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 564, in find_element_by_class_name
    return self.find_element(by=By.CLASS_NAME, value=name)
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 978, in find_element
    'value': value})['value']
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".button button--wide"}
  (Session info: chrome=77.0.3865.120)

While the button to access the messaging page is of the button button--wide class. In fact, in the source code there is:

<a class="button button--wide" data-ga-event-category="Listing Details" data-ga-event-action="clicked" data-ga-event-label="contact-box-email" href="/flatshare/flatshare_detail.pl?flatshare_id=14110387&amp;mode=contact&amp;submode=byemail&amp;flatshare_type=offered&amp;search_id=896264077&amp;search_results=%2Fflatshare%2F%3Fsearch_id%3D896264077%26&amp;city_id=9&amp;featured=&amp;alert_id=&amp;alert_type=&amp;upgrade_required=0&amp;" title="Email advertiser" rel="nofollow"><span><i class="far fa-envelope"></i>&nbsp;&nbsp;Message</span></a>

Trying find_element_by_css_selector('.button.button--wide')

Unfortunately, it tells me that I can't interact with the element:

(roo_env) (base) C:\Users\antoi\Documents\Programming\roomfinder>python test_message.py
http://iphoneapp.spareroom.co.uk/flatshares/14110387

DevTools listening on ws://127.0.0.1:52677/devtools/browser/4965ddbe-4b24-4ae7-a7f5-e44a8cbf2eef
Traceback (most recent call last):
  File "test_message.py", line 25, in <module>
    contact_room(14110387)
  File "test_message.py", line 23, in contact_room
    button_element.click()
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\webelement.py", line 80, in click
    self._execute(Command.CLICK_ELEMENT)
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\webelement.py", line 633, in _execute
    return self._parent.execute(command, params)
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
  (Session info: chrome=77.0.3865.120)
3
  • find by class_name is buggy, apparently. You should always use css. Commented Nov 8, 2019 at 23:49
  • Hi! Did you try my updated answer? Any updates? Thanks. Commented Nov 12, 2019 at 9:55
  • @RatmirAsanov Not yet, I was off. Will do, thank you for your help Commented Nov 13, 2019 at 9:29

4 Answers 4

2

Correct CSS Selector is: .button.button--wide:

enter image description here

So, in your case, it will be:

...
button_element = driver.find_element_by_css_selector(".button.button--wide")
...

UPD: Also, you can try to use explicit wait for locating element:

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

...
button_element = ui.WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".button.button--wide")))
button_element.click()

And completely working code is:

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


API_LOCATION = "http://iphoneapp.spareroom.co.uk"
API_DETAILS_ENDPOINT = "flatshares"
ID = "14110387"
URL = "{location}/{endpoint}/{id}".format(
    location=API_LOCATION, endpoint=API_DETAILS_ENDPOINT, id=ID)

DRIVER = webdriver.Chrome()
DRIVER.get(URL)
ui.WebDriverWait(DRIVER, 10).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "a.button.button--wide"))).click()

I hope it helps you!

Sign up to request clarification or add additional context in comments.

6 Comments

Oh, are you sure? I get selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: An invalid or illegal selector was specified
@IggyPass, I changed (extended) my answer a little bit. Check it, please.
@IggyPass, CSS Selector is correct (according to your provided HTML of element -- see screenshot above). Any updates? Thanks.
@IggyPass, I see your last error message. My updated answer must fix your problem. Thanks.
Thanks, unfortunately I get selenium.common.exceptions.TimeoutException: Message:
|
1

The reason you were getting json in the browser because you have passed wrong parameter value in the function. You have provided api_details_endpoint this variable instead of details_endpoint. Second thing with that class_name there is 11 elements to get unique use parent element as well.

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

api_location = 'http://iphoneapp.spareroom.co.uk'
api_search_endpoint = 'flatshares'
api_details_endpoint = 'flatshares'

location = 'http://www.spareroom.co.uk'
details_endpoint = 'flatshare/flatshare_detail.pl?flatshare_id='

def contact_room(room_id):
    url = '{location}/{endpoint}/{id}?format=json'.format(location=api_location, endpoint=details_endpoint, id=room_id)
    print(url)
    driver_path = 'C:\Program Files\chromedriver'
    driver = webdriver.Chrome(executable_path = driver_path )  # Optional argument, if not specified will search path.
    # Go to your page url
    driver.get(url)
    WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"li.emailadvertiser > .button.button--wide"))).click()
    # Get button you are going to click by its id ( also you could use find_element_by_css_selector to get element by css selector)
    # button_element = driver.find_element_by_class_name('button button--wide')
    # button_element.click()

contact_room(14110387)

Comments

0

The element might be not getting loaded so it might gives no such element error. You can add

driver.implicitly_wait(15)

line before searching for element. (In this case, before driver.find_element_by_class_name('button button--wide') line.)

Don't worry it won't be wait 15 seconds. Whenever it the element is loaded, selenium will find it.

Comments

0

You can try this get the element by xpath (is more simple):

Take a look for this post: Is there a way to get the XPath in Google Chrome?

button_element = driver.find_element_by_xpath('your_xpath')
button_element.click()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.