python clicking a button on a webpage
I currently have a script that logs me into a website and I want to have it click a button on the website if it is currently not clicked. Here is the info for the button:
When the button is already active:
When the button is not active:
I am only looking to click it when class=»button grey toast track-click»
What is the best way to do this? I currently use urllib2 and mechanize to login and check a few forms currently. Thanks!
1 Answer 1
When I compare the two tags I see that the difference is for the class tag. So if you can read it then you’re done
You can do it with Selenium if you like
Step 1: find the XPath — Get the XPath of the button: for that right open the page in Chrome click on it and select Inspect element — It will open the html file and right click on the highlighted line and select copy Xpath — Copy the XPath in NotePad
Now that you have the XPath you can select the button via a Python script and query the attributes
Selenium + Python
В этой статье вы узнаете как пользоваться связкой PyCharm + Python + unittest + Selenium + JavaScript.
Для лучшего понимания пригодятся начальные знания Python и JavaScript
Основные методы работы в Selenium не зависят от языка, на котором вы пишете тест. Они разобраны в статье «Основы Selenium»
Я для работы использую PyCharm . Как добавить в PyCharm Selenium читайте здесь
Можете взять другой IDE или запускать из-под Linux ,но не советую пытаться запускать тесты Selenium из Подсистемы Windows для Linux так как в bash для Windows нет поддержки графики по умолчанию. Можно заморочиться и поставить что-то вроде Xming, но я не стал пробовать.
В этой статье я постараюсь показать развитие тестировщика на Python + Selenium.
Сначала попробуем запускать Selenium Webdriver и выполнять разные задачи, как средствами, встроенными в Webdriver, так и включая различные JavaScript манипуляции с DOM.
Затем перейдём к использованию unittest, а потом посмотрим что делать, может быть читатели что-то подскажут.
Код будет для Selenium 4 старую версию можете найти здесь
Установка
Первым делом нужно убедиться что установлен Python
Затем нужно убедиться что установлен pip
pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)
Если всё в порядке, то selenium можно установить через pip как обычный пакет
python3 -m pip install selenium
Collecting selenium Downloading selenium-3.141.0-py2.py3-none-any.whl (904 kB) |████████████████████████████████| 904 kB 8.7 MB/s Requirement already satisfied: urllib3 in /usr/lib/python3/dist-packages (from selenium) (1.25.8) Installing collected packages: selenium Successfully installed selenium-3.141.0
Выбор драйвера
После установки Selenium нужно скачать драйверы для нужных браузеров.
Это действие не зависит от того на каком языке программирования вы планируете писать тест.
Подробную инструкцию можете прочитать в статье Selenium
Когда путь до драйвера добавлен в PATH можно подключать нужный браузер в ваш Python код.
Firefox драйвер называется Gecko Driver и подключается так
from selenium import webdriver driver = webdriver.Firefox()
Chrome аналогично. Вместо слова driver вы можете придумать свои называния. Например chdriver и ffdriver.
from selenium import webdriver driver = webdriver.Chrome()
Поиск элеменотов
Есть много способов искать элементы, но их объединяет необходимость импортировать By
from selenium.webdriver.common.by import By
find(By. ID , «id элемента» )
find_element(By. CLASS_NAME , «имя класса» )
find_element(By. CSS_SELECTOR , «имя селектора» )
Простой тест
Рассмотрим скрипт simple.py
Зайдём на сайт и проверим, что в названии есть фраза «О Финляндии и путешествиях» найдём изображение по имени класса, найдём изображение по имени селектора
from selenium import webdriver from selenium.webdriver.common.by import By driver = webdriver.Chrome() url = «https://www.heihei.ru/» driver.get(url) assert «HeiHei.ru» in driver.title image = driver.find_element(By.CLASS_NAME , «w100» ); # Returns only the first element with the class image2 = driver.find_element(By.CSS_SELECTOR , 'img.w100') # Returns only the first element with the css selector print ('image2: ') print (image2) driver.close()
DevTools listening on ws://127.0.0.1:1347/devtools/browser/a85188e9-53b2-45b4-b538-65e8a84670cb [9184:8460:1208/004903.366:ERROR:ssl_client_socket_impl.cc(983)] handshake failed; returned -1, SSL error code 1, net_error -207 image2:
headless
Для «невидимого» запуска Selenium Webdriver нужно использовать опцию headless
Это очень полезный режим для тестирования в связке с CI/CD инструментами.
Чтобы пользоваться этим режимом нужно импортировать Options
from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument(«—headless») driver = webdriver.Chrome(options=chrome_options)
Можно добавить логику на основе переданного аргумента. Я обычно добавляю лог.
chrome_options = Options() if headless == True : chrome_options.add_argument( «—headless» ) print ( «Headless, headless and wild» ) else : print ( «Running head over hills» ) driver = webdriver.Chrome(options=chrome_options)
Как нажать на кнопку
Чтобы нажать на кнопку нужно найти элемент и использовать функцию click()
Например, найдём элемент button с классом new-button и нажмём на него.
driver.find_element(By.CSS_SELECTOR , button.new-button» ).click()
Можно искать по id
driver.find_element(By.ID , «loginButtonId» ).click()
Также допустимо сперва присвоить переменной результат поиска и потом вызвать click()
loginButton = driver.find(By.ID , «loginButtonId» ) loginButton.click()
Поиск по тексту
Задача: кликнуть на кнопку с текстом LOGIN
Известно: div с текстом LOGIN имеет класс title, но элементов этого класса несколько и какой по счёту нам нужен неизвестно
Находим все элементы класса title
title_class = driver.find_elements_by_class_name( «title» ) for el in title_class: if el.text == «LOGIN»: login_button = el login_button.click()
Дождаться загрузки элемента
Допустим, вам нужно дождаться загрузки элементов с классом Buttons
Вы готовы ждать максимум десять секунд.
driver.implicitly_wait(10) buttons = driver.find_elements_by_class_name( «Buttons» )
Если элементы появятся быстрее, специально ждать десять секунд драйвер не будет.
Таким образом implicit wait это либо пока элемент не нашёлся, либо пока лимит времени не истёк. Лимит вы устанавливаете сами для каждого случая отдельно.
Автозаполнение формы
Пример автозаполнения формы на сайте. Может пригодиться, если вы сделали форму и хотите время от времени проверять всё ли на ней работает.
Сперва убедимся, что в названии страницы присутствует «Коста-дель-Соль» затем автоматически заполним форму.
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import Select driver = webdriver.Chrome() url = «https://www.heihei.ru/Spain/renovation/costa_del_sol/» driver.get(url) assert «Коста-дель-Соль» in driver.title driver.find_element(By.ID , 'container' ) municipality_list = Select(driver.find_element(By.NAME , 'municipality' )) municipality_list.select_by_visible_text( 'Марбелья' ) area_list = Select(driver.find_element(By.NAME , 'price' )) area_list.select_by_value( 'area-larger100' ) bedrooms_list = Select(driver.find_element(By.NAME , 'bedrooms' )) bedrooms_list.select_by_value( '3-bedroom' ) meetingplace_list = Select(driver.find_element(By.NAME , 'meetingplace' )) meetingplace_list.select_by_visible_text( 'Хельсинки' ) your_name_form = driver.find_element(By.NAME , 'your_name' ) your_name_form.send_keys( 'Andrei' ) email_form = driver.find_element(By.NAME , 'email' ) email_form.send_keys( «heihei@heihei.ru» ) message_form = driver.find_element(By.NAME , 'message' ) message_form.send_keys( «TEST Message» ) sum_form = driver.find_element(By.NAME , «sum» ) sum_form.send_keys( «100» ) driver.find_element(By.CLASS_NAME , 'bookingbutton' ).click()
Пример реального теста на создание пользователя
Запускаем Chrome и заходим на сайт.
Логинимся, находим нужный пункт в верхнем меню — Tools открываем его.
Выпадает список — находим там нужный — User Profiles.
Заходим туда, заполняем все формы, сохраняем и проверяем — не получили ли мы предупреждение о том, что пользователь с таким именем уже существует. Проверяем не выдал ли фреймворк, на котором сделан сайт, необработанную ошибку.
В этом примере поиск элементов по классу сделан средствами JavaScript, затем найденным элементам присвоены определённые id и уже по этим id из находит Selenium Webdriver
Не копируйте этот тест себе пока не прочитаете всю статью. Очень много чего ещё можно оптимизировать
from selenium import webdriver from selenium.webdriver.chrome.options import Options import time from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import Select driver = webdriver.Chrome() driver.get(» http://your_url.ru/test/ «) driver.set_window_size(1920, 1024) driver.find_element_by_id('someDivId') time.sleep(2) driver.execute_script(«»» div1 = document.getElementById( «someDivId» «); div1.style.backgroundColor = 'red'; «»») time.sleep(2) driver.execute_script( «»» window.scrollBy(0,1000) div1 = document.getElementById('someDivId'); div1.style.backgroundColor = 'red'; div2 = div1.children; div2[0].style.backgroundColor = 'green'; div3 = div2[0].children; div3[0].style.backgroundColor = 'yellow'; table1 = document.getElementsByClassName('v-formlayout-margin-top'); array1 = document.getElementsByClassName('v-textfield'); array1[0].style.backgroundColor = 'violet'; array1[0].style.padding = '40px'; array1[0].id = 'usernameId'; array1[1].style.backgroundColor = 'pink'; array1[1].style.padding = '40px'; array1[1].id = 'passwordId'; idCandidates = document.getElementById('some-uid-5') div1.style.backgroundColor = 'grey'; button1 = document.getElementsByClassName('v-button'); button1[0].id = 'loginButtonId'; console.log(div2.length); «»» ) usernameForm = driver.find_element_by_id('usernameId') usernameForm.send_keys('user') passwordForm = driver.find_element_by_id('passwordId') passwordForm.send_keys('password') loginButton = driver.find_element_by_id('loginButtonId') loginButton.click() print («Logged in successfully!») time.sleep(4) driver.execute_script( «»» topMenuElements = document.getElementsByClassName('v-menubar-menuitem'); toolsButton = topMenuElements[5]; toolsButton.style.color = 'red'; toolsButton.id = 'topToolsButton'; «»» ) topToolsButton = driver.find_element_by_id('topToolsButton') topToolsButton.click() print («Tools menu entered!») time.sleep(4) driver.execute_script( «»» toolsButtonBlockOfOptions = document.getElementsByClassName('v-menubar-submenu-top-menu'); console.log('—————————————— '+toolsButtonBlockOfOptions); toolsButtonBlockOfOptions[0].style.color = 'violet'; toolsButtonBlockOfOptions[0].id = 'toolsDropDownDiv'; toolsDropDownOptions = toolsButtonBlockOfOptions[0].children; console.log('——————————————2 '+toolsButtonBlockOfOptions[0]); toolsDropDownOptions[1].style.color = 'orange'; toolsDropDownOptions[1].id = 'usersProfilesId'; «»» ) time.sleep(2) userProfilesButton = driver.find_element_by_id('usersProfilesId') userProfilesButton.click() print («User Profiles menu entered!») time.sleep(4) driver.execute_script( «»» toolsAddUserButtonCandidates = document.getElementsByClassName('v-button'); toolsAddUserButtonCandidates[2].style.color = 'red'; toolsAddUserButtonCandidates[2].style.paddingRight = '150px'; toolsAddUserButtonCandidates[2].id = 'addUserButtonId'; «»» ) time.sleep(2) addUserButton = driver.find_element_by_id('addUserButtonId') addUserButton.click() time.sleep(2) driver.execute_script( «»» userNamFieldCandidates = document.getElementById('some-uid-85'); userNamFieldCandidates.style.color = 'red'; userNamFieldCandidates.style.paddingRight = '150px'; //userNamFieldCandidates[0].id = ''; «»» ) addUserUsername = driver.find_element_by_id('some-uid-85') addUserUsername.send_keys('testUserSelenium') time.sleep(2) addUserFirstName = driver.find_element_by_id('some-uid-87') addUserFirstName.send_keys('FirstNameSelenium') time.sleep(2) addUserLastName = driver.find_element_by_id('some-uid-89') addUserLastName.send_keys('LastNameSelenium') time.sleep(2) addUserPassword = driver.find_element_by_id('some-uid-91') addUserPassword.send_keys('password1') addUserUserTagId = driver.find_element_by_id('some-uid-93') addUserUserTagId.send_keys('12345') driver.execute_script( «»» userGroupSelectBlockCandidates = document.getElementsByClassName('v-select-select'); userGroupSelectBlockCandidates[0].style.color = 'red'; userGroupSelectBlockCandidates[0].style.paddingRight = '150px'; userGroupSelectOptions = userGroupSelectBlockCandidates[0].children; userGroupSelectOptions[1].style.color = 'blue'; userGroupSelectOptions[1].id = 'userGroupSelectOptionAdminId'; «»» ) time.sleep(2) selectUserGroupAdmin = driver.find_element_by_id('userGroupSelectOptionAdminId') selectUserGroupAdmin.click() #similar code exists — need to replace with a function if possible driver.execute_script( «»» saveButtonCandidates = document.getElementsByClassName('v-button'); saveButtonCandidates[4].style.backgroundColor = 'green'; saveButtonCandidates[4].style.color = 'red'; saveButtonCandidates[4].style.margin = '150px'; saveButtonCandidates[4].style.padding = '150px'; saveButtonCandidates[4].id = 'saveButtonId'; «»» ) time.sleep(2) saveButton = driver.find_element_by_id('saveButtonId') saveButton.click() print («Tried to create new user!») time.sleep(2) if driver.find_elements_by_xpath(«//*[contains(text(), 'Given user name is already in use')]»): print («WARNING LOG: \n User with this name already exists \n WARNING LOG END \n «) if driver.find_elements_by_xpath(«//*[contains(text(), 'RpcInvocationException')]»): print («ERROR LOG: \n RpcInvocationException \n ERROR LOG END \n «) #driver.close()
Импорт файлов
Если вам нужно загрузить файл с помощью Selenium — нажимать на кнопку загрузки не нужно.
Найдите элемент input (скорее всего) в котором триггерится загрузка. Выделите его и используйте .send_keys с указанием пути до файла
Допустим, что вы нашли этот элемент и его Или у него не было никакого id вообще, но вы присвоили ему этот id самостоятельно с помощью JavaScript
inputElement = driver.find_element_by_id(inputElementId) path orange»>\\ Users \\ andrei \\ Documents \\ Projects \\ projectName \\ products.csv» inputElement.send_keys(path)
Пример теста без использования специальных библиотек
Основное отличие от предыдущего примера — кликов на верхнее меню теперь несколько, поэтому скрипт клика на элемент верхнего меню оформлен как функция, которая принимает в качесте параметра название элемента меню, например Tools, и затем использует это название как ключ для внутреннего словаря — получает порядковый номер элемента и кликает на него.
Также в этом тесте будет загрузка файла. Пока что я не пользуюсь никакими библиотеками для тестирования, поэтому вся надежда на текстовый вывод.
from selenium import webdriver from selenium.webdriver.chrome.options import Options import requests import time import random from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import Select url2 = «http://someUrl:4880/path/» failedToConnect = False r = 0 try: r = requests.get(url2) except: print («Tried to connect to server but failed») failedToConnect = True # headless = True headless = False def testprojectName(headless) : # driver = webdriver.Chrome() chrome_options = Options() if headless == True : chrome_options.add_argument(«—headless») print («Running in headless mode») else : print («Running head over hills») # chrome_options.add_argument(«—headless») driver = webdriver.Chrome(options=chrome_options) # define functions def loginFunction(username, password): # expects that IDs are existing so need to assign # them before calling this function usernameForm = driver.find_element_by_id('usernameId') usernameForm.send_keys(username) passwordForm = driver.find_element_by_id('passwordId') passwordForm.send_keys(password) loginButton = driver.find_element_by_id('loginButtonId') loginButton.click() print («Logged in successfully!») def goToTopMenuFunction(MenuName): topMenuDict = < "Tools": 5, "Graphs": 4, "History": 3, "Reports": 2, "Shipments": 1, "Home": 0, >if MenuName in topMenuDict: print (f»Yes, < MenuName >is one of the keys in the topMenuDict dictionary») else : print (f» < MenuName >is not recognized as a top menu option») menu_number = topMenuDict[MenuName] print (f» < MenuName >menu is selected») driver.execute_script(f»»» console.log('0000 —————————————') console.log('Go to menu number < menu_number >'); console.log('0001 —————————————') console.log('Its name is < MenuName >'); topMenuElements = document.getElementsByClassName('v-menubar-menuitem'); console.log('1111—————————————') console.log(topMenuElements); topMenuButton = topMenuElements[ < menu_number >]; console.log('1122—————————————- ') console.log(topMenuButton); topMenuButton.style.color = 'red'; topMenuButton.id = ' < MenuName >topButton'; console.log(topMenuButton.id); «»») newButtonId = MenuName + 'topButton'; topMenuButton = driver.find_element_by_id(newButtonId) print (topMenuButton) topMenuButton.click() print (f» < MenuName >menu entered!») def checkForStackTrace(): if driver.find_elements_by_xpath(«//*[contains(text(), 'Given user name is already in use')]»): print («WARNING LOG:\n User with this name already exists \nWARNING LOG END \n «) if driver.find_elements_by_xpath(«//*[contains(text(), 'RpcInvocationException')]»): print («ERROR LOG:\n RpcInvocationException \nERROR LOG END \n «) def goToSubMenuOfTopMenuFunction(SubMenuName): topSubMenuDict = < "Server Settings": 0, "User Profiles": 1, "Server Log": 2, "My Settings": 3, "Locations": 4, "Integration Endpoints": 5, "Types": 6, "Test Data": 7, "Report fields customization": 8, "Companies": 9, "Product types": 10, >if SubMenuName in topSubMenuDict: print (f»Yes, < SubMenuName >is one of the keys in the topMenuDict dictionary») else : print (f» < SubMenuName >is not recognized as a top menu option») sub_menu_number = topSubMenuDict[SubMenuName] print (f» < SubMenuName >submenu is selected») driver.execute_script(f»»» subMenuButtonBlockOfOptions = document.getElementsByClassName('v-menubar-submenu-top-menu'); console.log('—————————————— '+subMenuButtonBlockOfOptions); subMenuButtonBlockOfOptions[0].style.color = 'violet'; subMenuButtonBlockOfOptions[0].id = 'subMenuDropDownDiv'; subMenuDropDownOptions = subMenuButtonBlockOfOptions[0].children; console.log('——————————————2 '+subMenuDropDownOptions[0]); subMenuDropDownOptions[ < sub_menu_number >].style.color = 'orange'; subMenuDropDownOptions[ < sub_menu_number >].id = ' < SubMenuName >Id'; «»») time.sleep(2) newButtonId = SubMenuName+'Id'; subMenuButton = driver.find_element_by_id(newButtonId) subMenuButton.click() print (f» < SubMenuName >menu entered!») def clickVbuttonFunction(vButtonName): vButtonDict = < "Add New User": 2, "Save": 4, "Import from CSV": 3, "Select file":4, >if vButtonName in vButtonDict: print (f»Yes,
Selenium + unittest
Как вы уже скорее всего знаете, в Selenium Webdriver нет никаких средств для написания тестов. Обычно вместе с Webdriver используют библиотеку того языка программирования, на котором работает программист-тестировщик.
В этой статье я пользуюсь Python 3 поэтому в качестве библитеки для тестирования могу выбрать unittest, nose или pytest.
В качестве альтернативы Python 3 можно использовать Java, C#, Javascript, Ruby или Kotlin
How to Click Button on Webpage with Python Requests Library?
![]()
I was wondering how exactly I would go about using python's requests library to click on buttons on a webpage. After I click on a button on a webpage I want to be able to access the page that I am redirected to.
As an example, if I wanted to access r/learnpython's homepage and then click the "Create Post" button to have the webpage redirect me to the page that lets me create a post, how would I use requests to do that?
Keep in mine that I do not want to go to the URL "https://www.reddit.com/r/learnpython/submit" directly. I want to be able to actively press the "Create Post" button in this example. I also don't want to use selenium or any other solution that requires me to have a the browser's GUI open.
I know this is basic but I can't for the life of me find a post that gives me a clear answer to this question. Thanks for your time.
Как нажать на кнопку на сайте python
Одним из наиболее используемых компонентов в графических программах является кнопка. В tkinter кнопки представлены классом Button . Основные параметры виджета Button:
command : функция, которая вызывается при нажатии на кнопку
compund : устанавливает расположение картинки и текста относительно друг друга
cursor : курсор указателя мыши при наведении на метку
image : ссылка на изображение, которое отображается на метке
pading : отступы от границ вилжета до его текста
state : состояние кнопки
text : устанавливает текст метки
textvariable : устанавливает привязку к элементу StringVar
underline : указывает на номер символа в тексте кнопки, который подчеркивается. По умолчанию значение -1, то есть никакой символ не подчеркивается
width : ширина виджета
Добавим в окно обычную кнопку из пакета ttk:
Для создания кнопки используется конструктор Button() . В этом конструкторе с помощью параметра text можно установить текст кнопки.
Чтобы разместить виджет в контейнере (главном окне), у него вызывается метод pack() . На ОС Windows мы получим следующую кнопку:

Конструктор Button определяет различные параметры, которые позволяют настроить поведение и внешний вид кнопки. Однако конкретный набор параметров зависит от того, используем ли мы кнопки из пакета tkinter или из пакета tkinter.ttk.
Обработка нажатия на кнопку
Для обработки нажатия на кнопку необходимо установить в конструкторе параметр command , присвоив ему ссылку на функцию, которая будет срабатывать при нажатии:
Здесь в качестве обработчика нажатия устанавливается функция click_button. В этой функции изменяется глобальная переменная clicks, которая хранит число кликов. Кроме того, изменяем текст кнопки, чтобы визуально было видно сколько нажатий произведено. Таким образом, при каждом нажатии кнопки будет срабатывать функция click_button, и количество кликов будет увеличиваться:

Отключение кнопки
Для ttk-кнопки мы можем установить отключенное состояние с помощью метода state() , передав ему значение «disabled». С такой кнопкой пользователь не сможет взаимодействовать:
При этом в метод state мы можем передать набор состояний, поэтому значение «disabled» передается внутри списка.