Playwright Python: Click Specific from Multiple Button - python

I want to Automate Fill Form using Playwright Python version. On Playwright NodeJS, I've been successfully to do the desired. Only when Porting the JS Script into Playwright Python API, it's kinda different.
The Web has Multiple Button (Submit and Random) with different Name. I can achieve both Button via get_by_role but I have no idea to get into Specific Submit Button:
#HTML
<form method="post" action="?query=MyAPI" enctype="multipart/form-data">
<table style="width: 100%">
<tbody><tr>
<td style="width: 146px">URL:</td>
<td><input name="url" type="text" style="width: 100%"></td></tr>
<tr><td style="width: 146px"> </td>
<td><br>
<input name="Random" type="random" value="Random" style="width: 97px">
<span>
<input name="Submit" type="submit" value="Submit" style="width: 157px">
</span>
</td></tr>
</tbody></table>
</form>
#JS Version
await page.getByRole('button', { name: 'Submit' }).click();
It seems the Python Version don't have { name: 'Submit'} feature, so I can only do ('button'). I'm not sure if I left something from the API, Already tried the following things but to not avail.
page.get_by_role('button').get_by_text('Submit').click()
page.get_by_role('button', {'name': 'Submit'}).click()
EDIT2
It's a Public UR, Here's The Submit Button XPath: /html/body/div[1]/div[2]/div[2]/article[1]/form/table/tbody/tr[2]/td[2]/span/input
EDIT1:
The Button is a part of Multipart Forms, it has no ID so I can't find any Alternative solution.

Try with:
await page.locator('//input[#value="Submit"]').click();
Or
await page.locator('//input[#type="submit"]').click();
Or
await page.locator('//input[#name="Submit1"]').click();
Then you are trying with Xpath, which should be enough if that is the only submit value/name/type of the page.
Basically with .locator you are locating the element and then with .click() you are making click on that element previously located
Fully working example
from playwright.sync_api import sync_playwright
import time
def run(playwright):
chrome = playwright.chromium
browser = chrome.launch(headless=False)
context = browser.new_context()
page = context.new_page()
page.goto("https://suip.biz/?act=iscloudflare")
page.locator("//input[#name='url']").fill("google.com")
page.locator("//input[#value='Submit']").click()
time.sleep(10)
browser.close()
with sync_playwright() as playwright:
run(playwright)

Related

How to "click" a button using requests

So, im trying to make a program that can click a button from multiple links, links that i will get from a list, but first i need to understand how can I do this with only one link. They all have the same HTML structure, but I dont know how to do this.
HTML:
<div class="_55wr">
<form method="post">
<input type="hidden" name="fb_dtsg" value="AQG7lSxYN2mb:AQFMMcWJcZtZ" autocomplete="off">
<input type="hidden" name="jazoest" value="22090" autocomplete="off">
<table class="btnBar">
<tbody>
<tr>
<td>
<button type="submit" value="Bloquear" class="_54k8 _52jg _56bs _26vk _56b_ _56bu" name="confirmed" data-sigil="touchable"><span class="_55sr">Bloquear</span></button>
</td>
<td>
<button type="submit" value="Cancelar" class="_54k8 _52jg _56bs _26vk _56b_ _56bt" name="canceled" data-sigil="touchable"><span class="_55sr">Cancelar</span></button>
</td>
</tr>
</tbody>
</table>
</form>
</div>
The idea is to click the first button ('<button type="submit" value="Bloquear"...').
Current code:
import requests
auth = ('email#email.com', 'pass')
payload = {}
url = 'https://www.example.com'
s = requests.Session()
res = s.get('https://www.example.com')
cookies = res.cookies
r = requests.post(url, cookies = cookies, auth = auth, verify = False, payload = payload)
I searched for similar questions, but every question was using some "id" ({'id':'value'}), which I don't have here. So, what value should i use in payload?
The requests library makes HTTP requests which means that it does not render the JS and it can not click buttons. Monitor your network behavior using google dev tools to know what data are sent to the server when you click a button, and then make a POST request sending the same data by the params keyword in the request. For example
data = {'button' : 'clicked1'}
r.requests.post('your_url.com', params = data)
For clicking buttons, I would personally use the selenium library which emulates the browser and provides its automation
I would use Selenium.
The code would be like so:
driver = webdriver.Firefox()
button = driver.find_element_by_xpath("//button[#value = \'Bloquear\']")
button.click()

Trouble clicking a three way toggle switch using selenium webdriver with Python

I want to click a three way toggle using selenium with python.The html element Ids are dynamic. So I have tried with an XPath where class contains a specific text! But I seeing 'element not found'/'element not visible' whole day!
I've tried with below line of code but no help.
browser.find_element_by_xpath("//*[contains(#class,'switch switch-three toggle ios') and contains(text(),'Available')]").click()
Here is the HTML code of the page and I want to click on - 'Available'
<label class="switch switch-three toggle ios" id="radio8526" onclick="" style="float: left; width: 300px; height:15px; margin-right: 20px;margin-left: 20px;">
<input id="available8526" value="available" onclick="setVersioningIdFun('8526');document.getElementById('toggleStateButton').click();;" name="onoffswitch8526" type="radio">
<label for="available8526" onclick="">Available</label>
<input id="unavailable8526" value="unavailable" onclick="setVersioningIdFun('8526');document.getElementById('toggleStateButton').click();;" name="onoffswitch8526" type="radio">
<label for="unavailable8526" onclick="">Unavailable</label>
<input id="archived8526" value="archived" onclick="setVersioningIdFun('8526');document.getElementById('toggleStateButton').click();;" name="onoffswitch8526" type="radio" checked="">
<label for="archived8526" onclick="">Finalised</label>
<a class="slide-button"></a>
</label>
From w3c documentation You can use this to solve your problem
browser.find_element_by_css_selector('input[id^="available"]').click()
You can just use the value attribute, e.g.
input[value='available']
You might need to add a wait for clickable to make sure the page has loaded. See this link for more info and some examples.

How to use Python Requests to submit radio button form?

I'm trying to learn about web interaction, specifically using Requests.
To that end, I'm interested in using Python with Requests to download a list of car parts from OReillyAuto.com But I'm running into a hiccup.
When I browse to this url, it should show me a list of brake pads and shoes for the type of car I've specified. However, it pops up a set of radio buttons asking if I want to view parts for the left side, right side, or all parts.
I cannot for the life of me figure out how to make that selection and get the HTML that I can see in the Chrome dev tools, which contains a list of brand-names, prices, etc.
I've tried a number of things, but this is what I have now:
#import HTTP libraries
import requests
#import HTML parsing libraries
import bs4
url = 'http://www.oreillyauto.com/site/c/search/Brake+Pads+&+Shoes/C0068/C0009.oap?model=G6&vi=1432754&year=2006&make=Pontiac'
answerURL = 'http://www.oreillyauto.com/site/ConditionSelectServlet?answer=-1'
print("Making request")
session = requests.Session()
session.headers.update({'referer': url})
r = session.get(answerURL)
print(r.status_code)
oreillyList = bs4.BeautifulSoup(r.text, "lxml")
print("Writing response...")
logfile = 'C:/Users/mhurley/Portable_Python/notebooks/' + output + '.log'
with open(logfile, 'w') as file:
file.write(oreillyList.prettify())
print("...done writing "+logfile)
I expect the log file that I write out to have about 5200 lines in it, as I do when I "View Page Source." However, I'm only getting about 3000 lines, and it looks like there are no parts in that list.
Maybe I really am getting what I think I am, but I'm not interpreting it correctly. Any tips for how to get past this dialog request?
EDIT: I suspect this is the HTML relevant to my purposes:
<div id="forcedVehicleQuestions" class="forcedUserInput" style="display: block; position: absolute; left: 50%; top: 40px; z-index: 6000; margin-left: -199px; margin-top: 0px;">
<div class="forcedContents clearfix">
<a class="btn-remove" onclick="closeForced('Search','question');">
<svg><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#shape-remove"></use></svg>
</a>
<form name="forcedQuestionsForm" id="forcedQuestionsForm">
<h2 class="sans">
More Product Info Required
</h2>
<p id="questionText" class="questionText">
Brake Pads - Position
</p>
<div id="forceQuestionsRadio">
<div class="form-row">
<label class="questionRadio checkbox-radio" id="questionRadio" for="Front">
<input type="radio" id="Front" name="answer" value="10219">
Front
</label>
</div>
<div class="form-row">
<label class="questionRadio checkbox-radio" id="questionRadio" for="Rear">
<input type="radio" id="Rear" name="answer" value="10290">
Rear
</label>
</div>
<div class="form-row">
<label class="questionRadio checkbox-radio" id="questionRadio" for="Show all">
<input type="radio" id="Show all" checked="" name="answer" value="-1">
Show all
</label>
</div>
</div>
<input id="questionSubmit" type="button" class="btn btn-green btn-shadow" value="Continue" onclick="setQuestionAnswer('Brake Pads - Position',document.forms['forcedQuestionsForm'].elements['answer'],'Show all');">
<div id="forcedVehicleQuestionsLoading" class="loading load-sm">
<div class="spinner"></div>
</div>
</form>
</div>
</div>
I'm having a hard time understanding how to interact with this <form> element. How can I make the "onclick=" happen so that the form gets submitted?
You will need to use a combination of Selenium + BeautifulSoup.
First, you'll use selenium to open the webpage in a browser, select the right radio button then submit the form.
After this, use BeautifulSoup to parse the page for the brakes.

selenium doesn't click flash upload in an embed tag

I tried to click on it directly and tried switching frame but it doesn't automate it when i manually click on it it works an d open a window popup to upload file
but using selenium it doesn't:
<div>
<input id="id" name="name" type="file" class="class" size="31" style="display: none; background-color: grey;" width="95" height="31">
<embed src="some_url" quality="high" width="95" height="31" id="fnameUploader" class="fileUploaderBtn" name="fnameUploader" type="application/x-shockwave-flash">
</div>

Unable to upload image/file in python using selenium webdriver

I'm unable to upload and save an image.
The following is the piece of code that facilitates file upload using the UI. At first, only the upload button is visible and once an image is selected from the uploader the save button is visible.
<td colspan="1" class="actions">
<input type="button" class="button" name="logo" id="logo-f-upload" value="Upload Image"/>
<input type="file" id="logo-upload" accept="image/*" name="logo-upload" style="display:none" />
<input type="submit" value="click to save" name="submit_logo_now" class="main submit_dm logo-save-focused" style="display: none"/>
</br>
</td>
I tried driver.find_element_by_id("logo-f-upload").send_keys(os.getcwd()+"/image_test.png")
and also
driver.find_element_by_id("logo-upload").send_keys(os.getcwd()+"/image_test.png")
but it doesn't throw any error at this stage but on the next where it says "element is not visible ..." ie. the save button. On the UI, when simulating this, the file uploader doesn't open but the file_upload button value changes to the path of the image and then breaks.
I believe this is the answer which is merely a JS hack: So the problem is that the logo-upload input has style set to display:none and due to this, selenium can't find the element. The solution that works for me is using javascript to set the style to display:block, after which using send_keys(img_path) works fine.
dr.execute_script("document.getElementById('logo-upload').setAttribute('Style','display:block')")

Categories