Python Selenium, the text of the next element - python-3.x

I can get the text of the first element. But I do not know how to go through the entire list and get the text of each element. Here is the tree from the site:
Screenshot
So I get the text of the first element:
driver.find_element_by_xpath("//a[#my-peer-link='participant.user_id']").click()
print(driver.find_element_by_xpath("//span[#ng-bind=\"'#' + user.username\"]").text)
In each
div class="md_modal_list_peer_wrap clearfix" ng-repeat="participant in
chatFull.participants.participants"
is contained
div class="md_modal_list_peer_name"
which contains
a class="md_modal_list_peer_name"
my-peer-link="participant.user_id">Олег
which you need to press. That is, execute:
driver.find_element_by_xpath("//a[#my-peer-link='participant.user_id']").click()
After that, a new window opens, from which I get the text of the element:
driver.find_element_by_xpath("//span[#ng-bind=\"'#' + user.username\"]").text
But there are several of these elements and I need to get the text with everyone:
div class="md_modal_list_peer_wrap clearfix" ng-repeat="participant in
chatFull.participants.participants"
How to do it?

Vladimir, I haven't done a careful analysis of this problem; however, could it be as simple as this?
Rather than using
driver.find_element_by_xpath("//span[#ng-bind=\"'#' + user.username\"]").text
could you use:
for span in driver.find_elements_by_xpath("//span[#ng-bind=\"'#' + user.username\"]"):
span.text
(Notice plural in `find_elements_by_xpath'.)

You'll need to click each element and store the text in a list:
So first use
elements_to_click = driver.find_elements_by_xpath("//a[#my-peer-link='participant.user_id']"
This will return a list of elements
Loop through those elements by
clicking on element
switch to the new window (When a new WindowHandle was created, otherwise skip this step.)
get the text via
driver.find_element_by_xpath("//span[#ng-bind=\"'#' + user.username\"]").text
store it in a list
close window (When a new WindowHandle is created, otherwise skip this step.)
switch to previous window

Related

can't click() an onclick element with selenium (tried text link, partial text link, xpath, css selector)

I need to scrap some data from this url:
https://www.cnrtl.fr/definition/coupe
The data/results I need to scrap are located in those 3 different tabs:
I'm unable to click on the onclick element which should let me switch from a tab to another.
Here the html code for one of the 3 onclick elements:
The 3 onclick elements differ from each other by the number at the end:
#COUPE1:
return sendRequest(5,'/definition/coupe//0');
#COUPE2:
return sendRequest(5,'/definition/coupe//1');
#COUPER:
return sendRequest(5,'/definition/coupe//2');
I tried to find them by link text, partial link text, xpath and css selector.
I've followed this thread:
Python + Selenium: How can click on "onclick" elements?
Also try the contains and text() method.
Without success.
There are a few ways you could do this. I chose the method I did because the page reloads causing the elements to become stale.
#Get the URL
driver.get("https://www.cnrtl.fr/definition/coupe")
#Find the parent element of the tabs
tabs = driver.find_element(By.ID, 'vtoolbar')
#Get all the list items under the parent (tabs)
lis = tabs.find_elements(By.TAG_NAME, 'li')
#loop over them (skipping the first tab, because that's already loaded)
for i in range(1, len(lis)):
#Execute the same JS as the page would on click, using the index of the loop
driver.execute_script(f"sendRequest(5,'/definition/coupe//{i}');")
#Sleep to visualise the clicking
time.sleep(3)

I need help in Python with displaying the contents of a 2D Set into a Tkinter Textbox

Disclaimer: I have only begun to learn about Python. I took a crash course just to learn the very basics about a month ago and the rest of my efforts to learn have all been research thru Google and looking at solutions here in Stack Overflow.
I am trying to create an application that will read all PDF files stored in a folder and extract their filenames, page numbers, and the contents of the first page, and store this information into a 2D set. Once this is done, the application will create a tkinter GUI with 2 listboxes and 1 text box.
The application should display the PDF filenames in the first listbox, and the corresponding page numbers of each file in the second listbox. Both listboxes are synched in scrolling.
The text box should display the text contents on the first page of the PDF.
What I want to happen is that each time I click a PDF filename in the first listbox with the mouse or with up or down arrow keys, the application should display the contents of the first page of the selected file in the text box.
This is how my GUI looks and how it should function
https://i.stack.imgur.com/xrkvo.jpg
I have been successful in all other requirements so far except the part where when I select a filename in the first listbox, the contents of the first page of the PDF should be displayed in the text box.
Here is my code for populating the listboxes and text box. The contents of my 2D set pdfFiles is [['PDF1 filename', 'PDF1 total pages', 'PDF1 text content of first page'], ['PDF2 filename', 'PDF2 total pages', 'PDF2 text content of first page'], ... etc.
===========Setting the Listboxes and Textbox=========
scrollbar = Scrollbar(list_2)
scrollbar.pack(side=RIGHT, fill=Y)
list_1.config(yscrollcommand=scrollbar.set)
list_1.bind("<MouseWheel>", scrolllistbox2)
list_2.config(yscrollcommand=scrollbar.set)
list_2.bind("<MouseWheel>", scrolllistbox1)
txt_3 = tk.Text(my_window, font='Arial 10', wrap=WORD)
txt_3.place(relx=0.5, rely=0.12, relwidth=0.472, relheight=0.86)
scrollbar = Scrollbar(txt_3)
scrollbar.pack(side=RIGHT, fill=Y)
list_1.bind("<<ListboxSelect>>", CurSelect)
============Populating the Listboxes with the content of the 2D Set===
i = 0
while i < count:
list_1.insert(tk.END, pdfFiles[i][0])
list_2.insert(tk.END, pdfFiles[i][1])
i = i + 1
============Here is my code for CurSelect function========
def CurSelect(evt):
values = [list_1.get(idx) for idx in list_1.curselection()]
print(", ".join(values)) ????
========================
The print command above is just my test command to show that I have successfully extracted the selected item in the listbox. What I need now is to somehow link that information to its corresponding page content in my 2D list and display it in the text box.
Something like:
1) select the filename in the listbox
2) link the selected filename to the filenames stored in the pdfFilename 2D set
3) once filename is found, identify the corresponding text of the first page
4) display the text of the first page of the selected file in the text box
I hope I am making sense. Please help.
You don't need much to finish it. You just need some small things:
1. Get the selected item of your listbox:
selected_indexes = list_1.curselection()
first_selected = selected_indexes[0] # it's possible to select multiple items
2. Get the corresponding PDF text:
pdf_text = pdfFiles[first_selected][2]
3. Change the text of your Text widget: (from https://stackoverflow.com/a/20908371/8733066)
txt_3.delete("1.0", tk.END)
txt_3.insert(tk.END, pdf_text)
so replace your CurSelect(evt) method with this:
def CurSelect(evt):
selected_indexes = list_1.curselection()
first_selected = selected_indexes[0]
pdf_text = pdfFiles[first_selected][2]
txt_3.delete("1.0", tk.END)
txt_3.insert(tk.END, pdf_text)

choosing a specific button from a list of identical buttons

I am making a battleships program, and after i created a list of identical buttons for a grid and inserting them all into one list, i want to be able to choose the button just clicked and delete it. How can i achieve this?
l = []
for i in range (100):
b = Button(battleship.frame, height = 1, width = 3, command = )
l.append(b)
#this is a snippet of what i have now but i am not sure what to do.
I have tried using lambda to give each button something unique to make them all different but i don't think this helps me in selecting the specific button that was just clicked.
Any suggestions?

Selenium's .text just giving blank lines

I've got this:
....
events = driver.find_elements_by_class_name("textblock")
for event in events:
content = event.text
print(content)
print(events)
This is the element, there are multiple. Each with different text:
<div class="textblock">example text</div>
Here's the output:
# one blank line for every item in list below...
# items below have been striped
[<selenium.webdriver.firefox.webelement.FirefoxWebElement (session="", element="")>, <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="", element="")> # and so on...
As you can see, instead of the text inside the div, I'm getting blank lines. Why is that?
Selenium will only return visible text. So, if this div is hidden in any way, or obstructed by another element, it will return an empty string because it is not visible. If you still need the text even if it's not visible, use javascript:
events = driver.find_elements_by_class_name("textblock")
for event in events:
content = driver.execute_script('return arguments[0].textContent;', event)
print(content)
print(events)
As per the HTML you have shared your code block looks good to me. However I would suggest you to get a bit granular and instead of using .text method we can use get_attribute("innerHTML") method as follows :
....
events = driver.find_elements_by_class_name("textblock")
for event in events:
content = event.get_attribute("innerHTML")
print(content)
print(events)

ExtJs layout + Window

While adding component dynamically, 'this.container is null' is displayed in firebug.
I have a window with some combo boxes say combo1, combo2, combo3 and a label. Based on the selection value of combo3 the 'label' field is removed and replaced with combobox or text field. i do this my using
form.items.removeAt(4);
form.items.insert(4, newItem); #here newItem can be combox/textfield
form.doLayout();
The form resides inside a panel.
When above lines are execueted. 'this.container is null' is displayed and component fails to insert/add in appropiate position.
Any suggestions?
You should not be modifying the underlying items collection. Use the remove/insert methods on the container.
Try to comment those lines line-by-line to see which one produces error like
form.items.removeAt(4);
//form.items.insert(4, newItem); #here newItem can be combox/textfield
//form.doLayout();
form.items.removeAt(4);
form.items.insert(4, newItem); #here newItem can be combox/textfield
//form.doLayout();
form.items.removeAt(4);
form.items.insert(4, newItem); #here newItem can be combox/textfield
form.doLayout();
Your problem could take place because of inserted/replaced object is no yet prepared when you try to insert it. Give us your newItem initilization code.
Upd
Or you can wrap your changing components (label, combobox, textfields) in a panel with card layout. And on change of combo3 simply select exact card in that panel.

Resources