I need to automate file uploading.
Here is a HTML code for path-to-file input field and button for manual uploading:
<div class="ctrl_div">
<input id="fileupload" class="hid" name="files" accept="application/zip" data-url="/Server/file/upload" type="file">
<button id="fileBtn" class="btn btn-primary" type="button">Upload</button>
</div>
When I try
driver.find_element_by_xpath('//input[#id="fileupload"]').send_keys(path_to_file)
I get ElementNotVisibleException
I also tried
driver.execute_script("document.getElementById('fileupload').style.visibility = 'visible';")
But input field remains invisible for webdriver.
Any ideas?
P.S. Adding implicit/explicit wait will not make a trick
You should try with
driver.execute_script(document.getElementById('fileUpload').style.display='block';");
Related
I apologize in advance if this is to detailed, I really tried my best to make my problem clear.
I need to upload a bunch of jpg files. Unfortunately if I don't automate the process it means days of clicking.
I'm using Python, Jupyter Notebook and chromebrowser to login and navigate through the interface, to where I want to upload the jpg. This is the stuff in my header.
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
import time
import datetime
import csv
import getpass
import os
import win32com.client
import pandas as pd
from selenium.webdriver.common.keys import Keys
Mostly I navigate by using some form of id, class, or xpath
element = driver.find_element_by_xpath("copy_of_the_xpath")
element.send_keys("password")
Or
element = driver.find_element_by_xpath("copy_of_the_xpath")
element.click()
So I navigate to the "selectFileBtn" which allows me to select a jpg for uploading. If I was doing this manually, I'd click this button, it would open a new window so I can select the file I want to. I would then have to click second button to confirm the upload "commitFileBtn"
<div style="float:right;">
<input type="button" name="" value="Select Material" id="selectFileBtn" class="button_basic">
<input type="button" name="" value="Upload" id="commitFileBtn" class="button_basic button_right">
</div>
Now I don't want to click the "selectFileBtn". I just want to give it the file. Normally I would just send the file using.
element = driver.find_element_by_xpath("xpath_to_selectFileBtn")
element.send_keys("file_to_be_uploaded")
But unfortunately "selectFileBtn" is type=button and I need type=file to send something. So I was really lost. Then I realized if I click the button the elements change from
<div style="float:right;">
<input type="button" name="" value="Select Material" id="selectFileBtn" class="button_basic">
<input type="button" name="" value="Upload" id="commitFileBtn" class="button_basic button_right">
</div>
to
<div style="float:right;">
<input type="button" name="" value="Select Material" id="selectFileBtn" class="button_basic">
<input type="file" style="display:none;" multiple="" accept=".jpg">
<input type="button" name="" value="Upload" id="commitFileBtn" class="button_basic button_right">
</div>
And if I then send my file to the xpath
element = driver.find_element_by_xpath('//*[#id="uploadCond"]/div/input[2]')
element.send_keys("file_to_be_uploaded")
of this element
<input type="file" style="display:none;" multiple="" accept=".jpg">
the whole thing works as intended.
Now I have a different problem: I can not make
<input type="file" style="display:none;" multiple="" accept=".jpg">
available through anything but clicking on it. And if I use the command
element.click()
then it takes 60+ seconds to open the window because some javascript black magic is happening and that is unfortunately to long. If I click it manually it almost instantly opens.
So I tried to create the node myself:
def create_material_node():
execu='''
var x = document.createElement("INPUT");
x.setAttribute("type", "file");
x.setAttribute("style", "display:none;");
x.setAttribute("multiple", "");
x.setAttribute("accept", ".jpg");
var element = document.getElementById("uploadCond").getElementsByTagName("div")[0];
element.insertBefore(x, element.children[1]);
'''
browser.execute_script(execu)
And to clone the node I wanted to send to:
def clone_node():
clone='''
var menu = document.getElementById("uploadCond").getElementsByTagName("div")[0].getElementsByTagName("input")[1];
var clonedMenu = menu.cloneNode();
var element = document.getElementById("uploadCond").getElementsByTagName("div")[0];
element.insertBefore(clonedMenu, element.children[1]);
'''
browser.execute_script(clone)
But both the creation and the clone couldn't upload the jpg I sent.
One thing I noticed was that the clone was missing an event listener called "change". I looked at change source panel but it was in Jquery and Javascript and I don't even know were to begin. I'm just stuck at this point. Does anyone know how I can automate uploading these files?
("#selectFileBtn").click(function(){
var extName = "";
if (self.getExtName) {
extName = self.getExtName();
}
$(this).parent().remove("input:file");
$(this).after("<input type='file' style='display:none;' multiple />");
$(this).next("input:file").attr("accept", extName).change(function(evt){
self.doUpload(evt.target);
}).click();
});
I am trying to use selenium webdriver to click on a button in a different class. The webpage is as follows:
<div class="fade tab-pane" id="mm9-tab-content" role="tabpanel">
<div class="button-submit">
<button class="btn btn-primary btn-lg btn-block post" id="download" type="button">Download</button>
</div>
</div>
<div class="fade tab-pane" id="dm3-tab-content" role="tabpanel">
<div class="button-submit">
<button class="btn btn-primary btn-lg btn-block post" id="download" type="button">Download</button>
</div>
</div>
the data is in 2 classes mm9-tab-content and dm3-tab-content. I want the system to click on the download button in the dm3-tab-content.
I tried using
driver.find_element_by_xpath('xpath = (//*#id="download")[1]').click()
to get the second instance of download but it doesn't seem to work. Any ideas?
Your XPath seem to be invalid. Try below instead
driver.find_element_by_xpath('(//*[#id="download"])[2]').click()
Note that, unlike in Python, in XPath nodes indexation starts from 1, so the second element should have index [2]
If you know the order in which the buttons appear and which one you want to use, you could find all the elements with the id="download", using find_elements_by_css_selector:
buttons = driver.find_elements_by_css_selector('#download')
Then, you can access each button in order.
To click the button under mm9-tab-content class use
driver.find_element_by_css_selector('#mm9-tab-content #download').click()
To click the button under dm3-tab-content class use
driver.find_element_by_css_selector('#dm3-tab-content #download').click()
I searched for answer before ask here but didn't get lucky enough. So here it goes, I am doing web scraping using python selenium. before choosing selenium I checked for mechanize, scrapy but I failed to execute some button clicks with them then I checked selenium it seems okay with some cons. I am saying all this because if I chose the wrong tool then please correct me before it is too late.
My question about selenium is how do I get all elements on webpage using xpath. eg: On webpage each webpage I got 10 forms and each of them has a button. So I want to get all the forms on web page to loop on them and click button one by one.
eg:
<form id="#F0">
<input type="button" name="itens" value="Items" class="texField2" onClick="somefunction()"/>
</form>
<form id="#F0">
<input type="button" name="itens" value="Items" class="texField2" onClick="somefunction()"/>
</form>
<form id="#F1">
<input type="button" name="itens" value="Items" class="texField2" onClick="somefunction()"/>
</form>
<form id="#F2">
<input type="button" name="itens" value="Items" class="texField2" onClick="somefunction()"/>
</form>
<form id="#F3">
<input type="button" name="itens" value="Items" class="texField2" onClick="somefunction()"/>
</form>
<form id="#F4">
<input type="button" name="itens" value="Items" class="texField2" onClick="somefunction()"/>
</form>
Another thing, What I am doing is I click on button on 1st form (it takes me to another page, I go back to history and click on 2nd button then go back to history and so on) it seems scraping would be slow. Is there any better way to do the same?
Thank you !!
Edit:
from selenium import webdriver
mydriver = webdriver.Firefox()
baseurl = """http://www.comprasnet.gov.br/consultalicitacoes/ConsLicitacao_Filtro.asp?numprp=&dt_publ_ini=24/02/2016&dt_publ_fim=10/03/2016&chkModalidade=1,2,3,20,5,99&chk_concor=31,32,41,42&chk_pregao=1,2,3,4&chk_rdc=1,2,3,4&optTpPesqMat=M&optTpPesqServ=S&chkTodos=-1&chk_concorTodos=-1&chk_pregaoTodos=-1&txtlstUf=&txtlstMunicipio=&txtlstUasg=&txtlstGrpMaterial=&txtlstClasMaterial=&txtlstMaterial=&txtlstGrpServico=&txtlstServico=&txtObjeto="""
mydriver.get(baseurl)
mydriver.find_element_by_id('ok').click()
buttons = mydriver.find_element_by_xpath("//form//input[#type='button']")
for button in buttons:
button.click()
You can get forms buttons by xpath with code below:
buttons = driver.find_elements_by_xpath(".//form//input[#type='button']")
And iterate them via simple for loop:
for button in buttons:
button.click()
Alternativelly you can use find_elements_by_css_selector function to get elements:
buttons = driver.find_elements_by_css_selector("input[type='button']")
For the following html, my code could not select the checkout button, what's wrong going with it?
My code:
browser.find_element_by_id('checkout').click()
browser.find_element_by_css_selector('input[value="Proceed To Checkout"]')
Html:
<div id="itemBasketButtons" class="clearfix">
<input id="updateOrder" class="button" type="button" value="Save Changes"></input>
<input id="checkout" class="button" type="button" value="Proceed To Checkout »"></input>
</div>
value="Proceed To Checkout »"
Note that "»" sign at the end. You probably should use
browser.find_element_by_css_selector(u'input[value="Proceed To Checkout »"]')
Can you find element itemBasketButtons?
browser.find_element_by_id('itemBasketButtons')
If so, try to select it, and then the second child (the checkout button)
browser.find_element_by_css_selector('#itemBasketButtons:nth-child(2)')
i am doing a small project in django by using python.
In that project, there is a table with list of pending task having columns: task_id,summary,description,due_date.
I have to give 'edit' button in each row so that one can edit the data of that particular row. But I am not able to identify the button click event in view page for the particular row.
Please somebody help me...
I'm assuming you're not talking about browser click events since you're tagging this with python and django only.
You can identify which <input type="submit"> element was pressed by giving it a name.
A user clicking on <input type="submit" value="edit" name="summary" /> will be identified by the presence of a summary key in request.POST
# form snippet
<input type="submit" value="Edit Summary" name="summary" />
<input type="submit" value="Edit Due Date" name="due_date" />
# view snippet
if request.POST.get('summary'):
print('user clicked summary')
elif request.POST.get('due_date'):
print('user clicked due date')
Below is my answer (an example) if you want to use "GET" instead of "POST".
Assuming that you want to get a value from the user input in html textbox whenever the user clicks 'edit' button, and then call a python function (mypythonfunction) that you wrote inside mypythoncode.py. Note that "btn" class is defined in a css file.
inside yourtemplate.html:
<form action="#" method="get">
<input type="text" value="8" name="mytextbox" size="1"/>
<input type="submit" class="btn" value="edit" name="mybtn">
</form>
inside view.py:
import mypythoncode
def mymethod(request):
if(request.GET.get('mybtn')):
mypythoncode.mypythonfunction( int(request.GET.get('mytextbox')) )
return render_to_response('App/yourtemplate.html')