Selenium Python, send number input value to li in HTML - python

I am automating a script that selects a product quantity, but this particular site uses +/- click buttons and has no dropdown or input field for the quantities that are read from CSV.
Rather than emulating button presses of the +/- for the quantities, you can manually edit the HTML below with the desired number and click the add to cart for the same effect.
Is it possible to edit the HTML when there is no form to do so on the site?
Or do I have to emulate clicks for the desired quantity.
I am using Pandas to read the CSV and is working code from another project.
Thank you if you can help
https://www.matsukiyo.co.jp/store/online/p/4902888248269
<ul class="count">
<li>数量</li>
<li class="minus disable">-</li>
<li class="num" id="addToCartQty" data-code="99">1</li>
<li class="plus">+</li>
</ul>
You can change the data-code="99">1</li> from 1 to 99 and it will update but is this possible in Selenium as I cannot find the right selector to do so. I have a feeling this is not possible?
The current code I am trying is sending clicks but I am not able to send the number of clicks I want and am stuck for a solution either way.
How can I send the value from the CSV to dictate the number of clicks?
Or how can I write the value to the li HTML?
driver.get(web_url+str(UPC[i]))
try:
driver.find_element(By.LINK_TEXT, "+").click
# I want to add the number of clicks here(str(quantity[i]))
link = driver.find_element_by_css_selector("p.button.cart")
link.click()
except:
print("Product Number: "+str(UPC[i])+" Sold Out!")

As I can see the element containing the count is located by id='addToCartQty' so what you can do is simply
driver.find_element_by_css_selector('#addToCartQty').sendKeys("your value");
or
driver.find_element_by_css_selector('#addToCartQty').sendKeys("value", "your value");
or
element = driver.find_element_by_css_selector('#addToCartQty')
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("arguments[0].value='enter the value here';", element);
Don't forger to change "your value" or 'enter the value here' with a number you wish to input there.

It is possible to edit the html and execute the script using execute_script() method
script="document.getElementsByClassName('num')[0].value="+your_value+" ;"
driver.execute_script(script)
You can check this by running the script in your browser console,it will induce your required value to the html tag.

Related

Python Selenium lists only one li repeatedly

I'm trying to make an attendance app, using Selenium; the script should read the names and click on a designated checkbox when a name is matched. What happens is that it keeps clicking on the first checkbox repeatedly. When I looked into it turns out that it only reads the first li only.
here's the HTML code
<div class="members">
<ul class="memberlist"></ul>
</div>
the li are generated via fetch API from the database
when I try these in python, it only reads the first li element over and over
for i in range(len(df)):
print(driver.find_element(By.XPATH,".//ul[#class='memberlist']/li/p").text)
for i in range(len(df)):
print(driver.find_element(By.CLASS_NAME,"name").text)
also, I tried the solution from this and I don't think this is the correct syntax
selenium python for loop printing only first element repeatedly
Update: as per dosas comment, this did list all the names instead of just one, then I wrote this to click on the checkboxes of the attendees.
for i in range(len(df)):
# match names of the sheet with the 'name' class in the webpage
if df['name'][i]==driver.find_elements(By.CLASS_NAME,"name")[i].text:
driver.find_elements(By.CLASS_NAME, week)[i].click()
print(driver.find_elements(By.CLASS_NAME,"name")[i].text)
else:
print('No match')
Now I have a different problem, the attendance excel sheet has to be in the same order as the list on the web page, otherwise, it'll show 'No match'. So how do I make it search the whole page for each particular name?

Python input text to randomly changed element without id or name

How can I input a text to a span element which is changing randomly at every page load?
I want to write a text on facebook with python but fb is changing span class etc to random at every page load...
If you load https://www.facebook.com/messages page the message input "Aa" is empty... and the element is the message is: <br data-text="true">
but if you write something it changes to: <span data-text="true">test message</span>
I tried:
message_input = driver.find_element_by_css_selector("br[data-text='true']")
message_input.send_keys('test message')
but ofc it makes no sense... not working.
Is there any way I can put text in that span element without importing anything?

How to extract the img title next to span as per the given HTML through Selenium and Python

I am making a web crawling for checking a kind of availability.
I want to check the title of the specific time. However, if the title is 'NO', there is no href, otherwise there is a href. Therefore, it's xpath depends on the title. The title name changes every time. So i can't check by xpath.
If I want to check the availability of 09:00~11:00, how can do that?
I tried to find by XPATH. However, since the XPATH changes as I told, I can't to check the specific time i want.
Thanks in advance.
Below is the HTML code.
<span class="rs">07:00~09:00</span><img src="../images/reservation_btn04.gif" title="NO"><br>
<span class="rs">09:00~11:00</span><img src="../images/reservation_btn04.gif" title="NO"><br>
<span class="rs">11:00~13:00</span><img src="../images/reservation_btn04.gif" title="NO"><br>
<span class="rs">13:00~15:00</span><img src="../images/reservation_btn03.gif" title="YES"><br>
<span class="rs">15:00~17:00</span><img src="../images/reservation_btn03.gif" title="YES"><br>
<span class="rs">17:00~19:00</span><img src="../images/reservation_btn03.gif" title="YES"><br>
<span class="rs">19:00~21:00</span><img src="../images/reservation_btn04.gif" title="NO"><br>
As per the HTML you have shared to check the availability of any timespan e.g. 09:00~11:00 you can use the following solution:
You can create a function() which will take an argument as the timespan and extract the availability as follows:
def check_availability(myTimeSpan):
print(driver.find_element_by_xpath("//span[#class='rs'][.='" + myTimeSpan + "']//following::img[1]").get_attribute("title"))
Now you can call the function check_availability() with any timespan as follows:
check_availability("09:00~11:00")
If the text 09:00~11:00 is fixed, you can locate the img element like this -
element = driver.find_element_by_xpath("//span[#class='rs' and contains(text(),'09:00~11:00')]/following-sibling::img")
To check whether the title attribute of the element is "YES" -
if element.get_attribute("title") == 'YES':
// do whatever you want
To get the href attribute of your required element-
source = driver.find_element_by_xpath("//span[#class='rs' and contains(text(),'09:00~11:00')]/following-sibling::img[#title='YES']/preceding-sibling::a").get_attribute("href")

Multiple iframe tags Selenium webdriver

I am trying to use selenium to send credit card info onto a site, and each element is contained in a separate iframe tag in the HTML. For example, the box to enter a credit card number is contained in the first iframe tag, and the card holder name is contained in the second iframe, and so on, and so forth. I am able to access the first iframe tag, and send the credit card number into the box, however I an unable to locate the cardholder name iframe tag, and thus cannot send the keys to enter a cardholder name. I'm wondering if there is a way to specifically search for the second (or an arbitrary number other than the first element) iframe tag with webdriver.
Here is the code I used:
driver.switch_to.frame(driver.find_element_by_tag_name("iframe"))
cc = driver.find_element_by_id("number")
cc.send_keys(credit_card_number)
This correctly found the first iframe tag which contains the field to enter a card number, and sent the appropriate keys
driver.switch_to.frame(driver.find_element_by_tag_name("iframe"))
driver.find_element_by_id("name").send_keys(cc_name)
This resulted in the following error: Message: no such element: Unable to locate element:{"method":"tag name","selector":"iframe"}
You have correctly found the first iframe tag which contains the credit card number field to enter the card number and sent the appropriate keys. Moving forward when you want to sent the appropriate keys to the card holder name field you need to be on the relevant frame first. So you have to switch back to the immedediate parent_frame() which contains both the iframe tags i.e. first iframe and second iframe and next try to switch to the second iframe to locate the card holder name field as follows :
# as there are multiple frames so find_element_by_tag_name("iframe") will not suffice and have to use unique css/xpath
driver.switch_to.frame(driver.find_element_by_xpath("xpath_of_iframe1"))
cc = driver.find_element_by_id("number")
cc.send_keys(credit_card_number)
driver.switch_to.default_content() #incase iframe1 and iframe2 are immediate child of the Top Level Content
driver.switch_to.frame(driver.find_element_by_xpath("xpath_of_iframe2"))
cc = driver.find_element_by_id("name")
cc.send_keys(cc_name)
Note : As per best practices you should not detect frames through find_element_by_tag_name("iframe") inpresence of multiple <iframe> tags on the webpage. The best way would be to use either Frame Name , Frame ID or Frame Index. You can find the detailed discussion in How can I select a html element no matter what frame it is in in selenium?.
After switching to first iframe , you have to switch back to default context (your main page containing multiple iframes) & then switch to next iframe .
So your pseudo code should look like
driver.switch_to.frame(driver.find_element_by_tag_name("iframe_1"))
driver.switch_to.defaultContent()
driver.switch_to.frame(driver.find_element_by_tag_name("iframe_2"))
driver.switch_to.defaultContent()
& so on

How to send keys to a difficult element in selenium (Python)

I am trying to click a small button, which has no "ID" or "Name", on a website. The only unique identifier is onclick, which is as follows:
onclick="submitForm('DefaultFormName',1,{'param1':'HXCTIMECARDACTIVITIESPAGEXgm7J5oT','serverValidate':'1uCdqvhJe','param2':'',event:'details|1'});return false;"
However, another button on the page has the following onclick:
onclick="submitForm('DefaultFormName',1,{'param1':'HXCTIMECARDACTIVITIESPAGEXgm7J5oT','serverValidate':'1uCdqvhJe','param2':'',event:'details|2'});return false;"
The only difference is a 1 vs. a 2 in the middle of the code. I tried to use a "find_element_by_css_selector" with the following code but it didn't work:
driver.find_element_by_css_selector(".x1p[onclick*='details|1']").click()
Another option would be selecting the preceding element, with the following code:
precedingbutton = driver.find_element_by_name('B22_1_6')
And then sending tab and then enter. However, after I send Tab, I don't know of a way to send Enter without assigning the Send_Keys command back to the preceding box, which deselects the button I want.
Let me know if you can help!
If you can locate the parent, you can locate the child, either with xpath or the nth-child css selector, relative to it.
Edit in response to comments:
Assuming by "2 elements away" you mean it is a sibling preceding the target, try something like td[name="B22_1_6"] + td + td. This is the sibling selector.
You can do it easily by
driver.find_element(By.XPATH, 'your xpath').click()
For finding the xpath , just inspect the button with firebug, and in html tab right click on selected element and click on Copy XPath.
Hope it will help you.

Categories

Resources