I am trying to fetch the station information from the website:
https://indiarailinfo.com/atlas
The table I'm trying to fetch is a hidden table which only appears on entering text in the text box
Hidden table
The below is the code of the div containing the required table (table class='dropdowntable")
<div style="top: 165px; left: 721px; display: none;" class="list hideslow">
<span style="display:none">LappGetStationList/nzm/0/1/0?&date=1601890451781&seq=9</span>
<table class="dropdowntable" numrows="1" cellspacing="0"><tbody><tr class="rowM1" rownum="0"><td style="display:none">748</td><td class="rcol" nowrap=""><span><span class="listmatch">NZM</span></span></td><td class="icol" nowrap=""><span>Hazrat Nizamuddin</span></td><td class="jcol" nowrap=""><span>NR-Old Delhi Div</span></td><td style="display:none;">NZM/Hazrat Nizamuddin</td></tr><tr class="rowm2" rownum="0"><td style="display:none">748</td><td><span nowrap=""> </span></td><td colspan="2" nowrap=""><span>Nizamuddin East/Sarai KaleKhan Bus Terminal 110013 Delhi NCT</span></td><td style="display:none">NZM/Hazrat Nizamuddin</td></tr><tr><td class="listfooter" colspan="5"><span width="10%" class="listfooterhidden">prev</span> <span width="10%" class="listfooterhidden">next</span> </td></tr><tr><td> </td></tr></tbody></table>
</div>
I have tried searching the table by class, but did't work. Any suggestions are welcome.
Update 1:
Here's the code I'm working with:
driver = webdriver.Chrome()
driver.get('https://indiarailinfo.com/atlas')
searchBox = driver.find_element(By.ID, 'TrkStnListBox')
searchBox.send_keys(code)
searchBox.click()
Approaches that I've tried:
1.dropDownTable = driver.find_element(By.PARTIAL_LINK_TEXT,'LappGetStationList')
2.dropDownTable = driver.find_element(By.CLASS_NAME,'list hideslow')
Now the following is where I'm having problems:
# hidden = driver.find_element(By.XPATH,"//input[#id='']")
driver.execute_script("arguments[0].setAttribute('style','visibility:visible;');", hidden)
driver.execute_script("arguments[0].click();", dropDownTable)
dropDownTableBody = dropDownTable.find_element(By.TAG_NAME,'tbody')
for entry in dropDownTableBody.find_elements(By.TAG_NAME,'tr'):
if entry.get_attribute('rownum')==0 and entry.get_attribute('class')=='rowM1':
for item in entry.find_elements(By.TAG_NAME,'td'):
if item.get_attribute('class')=='icol':
station.update({
'STATION NAME' : decodeText(item)
})
if item.get_attribute('class')=='jcol':
list = decodeText(item).split('-')
division = list[1][:list[1].find('Div')]
station.update({
'RAILWAY ZONE' : list[0],
'RAILWAY DIVISION' : division
})
print(station)
I have tried with chrome browser hope this will works for FF browser as well.
Once insert text in the search box you need to wait for table to populate it is autosuggest box.
Induce WebDriverWait() and wait for visibility_of_element_located()
Some of the table data are hidden so instead text use get_attribute("textContent")
Code:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver=webdriver.Chrome()
driver.get("https://indiarailinfo.com/atlas")
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.ID,"TrkStnListBox"))).send_keys("nzm")
table=WebDriverWait(driver,20).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'table.dropdowntable')))
for row in table.find_elements_by_xpath("./tbody/tr")[:2]:
for col in row.find_elements_by_xpath("./td"):
print(col.get_attribute("textContent"))
Console Output:
748
NZM
Hazrat Nizamuddin
NR-Old Delhi Div
NZM/Hazrat Nizamuddin
748
Nizamuddin East/Sarai KaleKhan Bus Terminal 110013 Delhi NCT
NZM/Hazrat Nizamuddin
Hope this is what you after.
I was able to fetch the table with
# Go to the website
driver = webdriver.Firefox()
driver.get("https://indiarailinfo.com/atlas")
# Send the search term
driver.find_element(By.ID, "TrkStnListBox").send_keys("nzm")
time.sleep(1)
# Read the Table
el = driver.find_element(By.CLASS_NAME, "dropdowntable")
But I could not reach the information in the table even after searching for "td" and "span" tags in the el variable. Maybe someone can take it from here.
Edit: Added a sleep comment to make sure that table is ready.
Related
I have homework to make a program in python with Selenium to send an email on hotmail. Everything was working fine till I had to find the "New Message" button (or any other button on that page to be honest)
Im constantly getting selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element:
I tried By : Class,Xpath,FullXpath,Css Selector. Can't find the name or Id
using the inspector.
I tried to make it wait with time.sleep
I really don't know what to do.
My code is here:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
driver = webdriver.Chrome(executable_path='C:\SeleniumDriver\chromedriver.exe')
driver.get("https://login.live.com/")
searchField = driver.find_element_by_name("loginfmt")
searchField.send_keys("")
nextButton = driver.find_element_by_id("idSIButton9").click()
passfield = driver.find_element_by_id("i0118")
passfield.send_keys("")
time.sleep(1)
signInButton = driver.find_element_by_xpath("//*[#id='idSIButton9']").click()
time.sleep(2)
try:
nobutton = driver.find_element_by_xpath("//*[#id='idBtn_Back']").click()
finally:
time.sleep(2)
appbutton = driver.find_element_by_xpath("//*[#id='O365_MainLink_NavMenu']").click()
time.sleep(10)
outlookbutton = driver.find_element_by_xpath("//*[#id='O365_AppTile_Mail']").click()
time.sleep(15)
newmessageButton = driver.find_element_by_xpath("//*[#id='app']/div/div[2]/div[2]/div[1]/div/div[1]/div/span/div/div/div/div/div[1]/div[1]").click()
time.sleep(6)
Requested HTML:
<div class="XayzgKk2Ga7sG02AhkQKJ"><div class="_1qPqjoFrRhZTOpwH-IJ2UP"><button type="button" class="ms-Button ms-Button--icon is-checked _3YkNJYKjMvYWaDLQ_t6D9- root-157" title="Toggle Left Pane" aria-expanded="true" aria-label="Toggle Left Pane" data-is-focusable="true"><span class="ms-Button-flexContainer flexContainer-158" data-automationid="splitbuttonprimary"><i data-icon-name="GlobalNavButton" aria-hidden="true" class="ms-Button-icon icon-167"></i></span></button></div><div class="_2nxYvsT9VmpG24V7lwcfcu"><div class=""><div class=""><button type="button" class="ms-Button GJoz3Svb7GjPbATIMTlpL _2W_XxC_p1PufyiP8wuAvwF lZNvAQjEfdlNWkGGuJb7d ms-Button--commandBar Gf6FgM99ZJ9S8H48pFMdB _3o6O4cjBEmQ4Q19oQJZZiF root-168" data-is-focusable="true"><span class="ms-Button-flexContainer flexContainer-158" data-automationid="splitbuttonprimary"><i data-icon-name="ComposeRegular" aria-hidden="true" class="ms-Button-icon _1y8YJ1XNBkLjckwryuEz2e icon-172"><span role="presentation" aria-hidden="true" class="w_jrWE2b2u-icz2udikRM"><svg class="_9fiU2J67uJPVP0DBdOFMW" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.85 1.85a.5.5 0 10-.7-.7l-8 8L6 10l.85-.15 8-8z"></path><path d="M4.5 2A2.5 2.5 0 002 4.5v7A2.5 2.5 0 004.5 14h7a2.5 2.5 0 002.5-2.5v-5a.5.5 0 00-1 0v5c0 .83-.67 1.5-1.5 1.5h-7A1.5 1.5 0 013 11.5v-7C3 3.67 3.67 3 4.5 3h5a.5.5 0 000-1h-5z"></path></svg></span></i><span class="ms-Button-textContainer textContainer-159"><span class="ms-Button-label uHWG8PYRNYDO2895_TmUG label-170" id="id__6">New message</span></span></span></button></div></div></div></div>
The "New message" button would be this selector in xpath:
"//button[contains(., 'New message')]"
Also, you might have an easier time choosing the correct selector if you use a record/playback/export tool to generate a script for you. Since you're already using Python, I recommend the SeleniumBase Recorder: https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/recorder_mode.md (It should help you generate a full script with selectors more easily.)
The reason is, once you click on outlook on first windows a new tab is opened and there we have a new message button. So in order to click on that, you would have to make sure that Selenium is switching to the new tab.
first_win_handle = driver.current_window_handle
outlookbutton = driver.find_element_by_xpath("//*[#id='O365_AppTile_Mail']")
outlookbutton.click()
all_win_handles = driver.window_handles
driver.switch_to.window(all_win_handles[1])
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='New message']/ancestor::button"))).click()
Imports:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
You are trying to find the element by id, but the element does not have an id. So that does not work.
You will either have to ensure the element gets that correct id, or use a different way to locate it.
You might try finding it by Css Selector:
'button[data-automationid="splitbuttonprimary"]'
Make sure to use the right quotes. Try this in the inspector first and you should find it. If you do not: it will not work, no matter the code.
If you see multiple hits then the css is not specific enough, and you will need to find a more specific way to locate it.
That selector basically means: an element of type "button" with attribute "data-automationid" with value "splitbuttonprimary". You can read more about locating specicif elements, css selectors, html elements and attributes here
I am trying to find an link text but after a specific image but i can't find a way to do it properly with Selenium . My code is just down bellow
browser.get(URL)
browser.find_element_by_xpath('//img[#src="Images"]')
browser.find_element_by_partial_link_text("Bla").click()
I need to start my partial link text selection after the specific xpath. Do you know an easy way to do this ?
This is the architecture of the html page (it's not public and it's just a portion of it ):
<tr style="background-color:#E5E5E5;font-size:9pt;">
<td align="center" style="width:70px;">05/03/2018</td><td align="center" style="width:40px;">
<img id="1" src="Images" style="border-width:0px;">
</td><td>
<span id="2"></span>
<a id="3" href="javascript:OuvreFenetre(3683826,241258727)">Blabla</a>
<span id="4"></span>
</td>
</tr>
I locate the img with the scr="Images" but i need to select the hyperlinks just after that (call here "Blabla").
I'd probably do something like this :
if driver.find_element_by_xpath('//img[#src="src"]').is_displayed():
driver.find_element_by_partial_link_text("words").click()
or if you want to introduce WebDriverWait, use it like below : (more reliable solution)
wait = WebDriverWait(driver, 10)
if wait.until(EC.visibility_of_element_located((By.XPATH, "your xpath here"))).is_displayed():
driver.find_element_by_partial_link_text("words").click()
or If anchor tag is child of image tag the probably you can do like this : //img[#src="src"]/a[contains(#href, ' href here')]
Imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Update 1 :
You can select anchro tag based on Image src like below :
//img[contains(#src, 'Images')]/following-sibling::a
so instead of these two lines :
browser.find_element_by_xpath('//img[#src="Images"]')
browser.find_element_by_partial_link_text("Bla").click()
You can use the above xpath like this :
browser.find_element_by_xpath("//img[contains(#src, 'Images')]/following-sibling::a").click()
or
//img[contains(#src, 'Images')]/following-sibling::a[contains(#href, 'javascript')]
Update 2:
Use the below xpath :
//img[contains(#src, 'Images')]/../following-sibling::td/a
I am trying to make an crawler/auto clicker on python where my target is to click all row header in a table to expand them and show the nested rows. I cannot seem to find the correct selector to use, I tried to use driver.find_elements_id, driver.find_elements_xpath, but it isnt working.
here is what i am using
PATH = "C:/Users/Downloads/chromedriver.exe"
driver = webdriver.Chrome(PATH)
driver.get("https://int.soccerway.com/")
link = driver.find_elements_id("tr")
link.click()
and here is a snippet of the website
<tr class="group-head clickable " id="date_matches-1886" stage-value="14">
<th colspan="4"><h3><span class="flag_16 left_16 australia_16_left">Australia - Queensland NPL Youth League</span></h3></th>
<th class="competition-link"> <span>More…</span></th>
</tr>
id should be date_matches-1886 instead of tr in your example. You may be instrested in the function called find_element_by_tag_name. But I think it is better to use find_element_by_class_name('clickable') in your case. Have a look at Locating Elements for more.
from selenium import webdriver
PATH = "C:/Users/Downloads/chromedriver.exe"
driver = webdriver.Chrome(PATH)
driver.get('https://int.soccerway.com/')
link = driver.find_elements_by_class_name('clickable')
link[0].click()
link[2].click()
I'm trying to iterate through a certain column of rows on a table/grid of an HTML page with I assume is a dynamic angular element.
I have tried to iterate through the rows by creating a list of common xpaths between each row. This only help me achieve 32 rows and not the full amount which is 332. I also tried waiting to see if the webpage would load and then have the full amount of web-elements. Then I tried to run a loop on searching for similar xpaths by scrolling down to the last element in the list. None of these ways helped me to iterate through the rows. Also I will not be able to share the website since the website is private.
python
webelement = []
driver.implicitly_wait(20)
ranSleep()
for webelement in driver.find_elements_by_xpath('//a[#class="ng-pristine ng-untouched ng-valid ng-binding ng-scope ng-not-empty"]'):
driver.implicitly_wait(20)
html for the rows
<a ng-model="row.entity.siteCode"
ng-click="grid.appScope.openSite(row.entity)"
style="cursor:pointer"
class="ng-pristine ng-untouched ng-valid ng-binding ng-scope ng-not-empty">
Albuquerque
<span title="Open defect(s) on site"
ng-show="row.entity.openDeficiencies"
style="background-color:yellow; color:#000;"
class="ng-hide">
!
</span>
</a>
I expect to be able to click all the links in each row once this is solved
Here is the snippet of the html code
<div id="table1" class="container-fluid">
<div ui-i18n="en"
class="grid advanceSearch ui-grid ng-isolate-scope grid1554731599680"
id="grid1" ui-grid="gridOptions"
ui-grid-expandable="" ui-grid-rowedit=""
ui-grid-resize-columns="" ui-grid-selection=""
ui-grid-edit="" ui-grid-move-columns="">
<!-- TODO (c0bra): add "scoped" attr here, eventually? -->
<style ui-grid-style="" class="ng-binding">
.grid1554731599680 {
/* Styles for the grid */
}
here is how the page looks with the table format
Here is the rows that I want to click through all of them
You might still be able to increment through each link by appending to the class name, as they seem to be a little unique in nature and using the last number as a char from the alphabet. Perhaps something like below could work :) Expanding on the classname's last character, in-case there's an increase, should solve the problem of there being more than 26.
Steps taken: increment classnames >append successes to list >move to link within list >click link >List item
import string
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
alpha = string.ascii_uppercase
successfulIncs = []
for char in alpha:
className = 'ng-pristine.ng-scope.ui-grid-coluiGrid-000' + char
try:
driver.find_elements_by_class_name(className)
successfullIncs.append(className)
except NoSuchElementException:
print("Element not found")
### First move to our element
for line in successfulIncs:
link = WebDriverWait(driver, 3).until(EC.visibility_of_element_located
(By.CLASS_NAME, line))
ActionChains(driver).move_to_element(link).perform()
#Click
ActionChains(driver).move_to_element(link).click(link).perform()
I've written a script in python with selenium to click on a certain link in a webpage to download an excel file. However, when I execute my script, it throws timeout exception. How can I make it work? Any help will be greatly appreciated.
Link to the site: webpage
Script I've tried with:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)
driver.get('replace_with_above_link')
item = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".hasmore #dlink")))
item.click()
driver.quit()
Html elements which contain the dropdown options:
<li class="hasmore drophover"><span>Share & more</span><div><ul><li><button class="tooltip" tip="Use a customizable report creator that can<br>output HTML, CSV, or a shareable link." id="share_on_ajax_result_table">Modify & Share Table</button></li><li><button class="tooltip" tip="Get a bit of widget code to emed this table on your site">Embed this Table</button></li><li><button class="tooltip" tip="Convert the table below to comma-separated values<br>suitable for use with excel">Get as Excel Workbook (experimental)</button><a id="dlink" style="display: none;"></a></li><li><button class="tooltip" tip="Export table as <br>suitable for use with excel">Get table as CSV (for Excel)</button></li><li><button class="tooltip" tip="">Strip Mobile Formatting</button></li><li><a id="a_ajax_result_table" name="ajax_result_table" href="#ajax_result_table::none">Copy Link to Table to Clipboard</a></li><li><button class="tooltip" tip="">About Sharing Tools</button></li><li><button class="tooltip" tip="">Video: SR Sharing Tools & How-to</button></li><li><button class="tooltip" tip="">Video: Stats Table Tips & Tricks</button></li></ul></div></li>
Location of that file in that webpage (the desired link is marked with pencil):
Target link is hidden and so wait for its visibility will always fail. You should try to handle button node instead:
item = wait.until(EC.visibility_of_element_located((By.XPATH, "//li[span='Share & more']")))
item.click()
wait.until(lambda driver: "drophover" in item.get_attribute("class"))
item.find_element_by_xpath("//button[.='Get as Excel Workbook (experimental)']").click()
As you are trying to click on the link with text as Get as Excel Workbook (experimental) and as per your comment you are already able to click on the Share&more link in the first place and found it working next your intended <a> tagged element contains the attribute style set to display: none;. So to invoke click() to download you can use the following code block :
Get_as_Excel_Workbook_link = driver.find_element_by_xpath("//li[#class='hasmore drophover']//ul//li//a[#id='dlink']")
driver.execute_script("arguments[0].removeAttribute('style')", Get_as_Excel_Workbook_link)
Get_as_Excel_Workbook_link.click()
Update A
As per your comment :
I am not sure if the xpath which you have used is a valid one or not :
"//li[a[#id='dlink']]/a"
You tried using :
Get_link = driver.find_element_by_xpath("//li[a[#id='dlink']]/a")
print(Get_link.get_attribute("outerHTML"))
But why? Is there any necessity?
As per my research and analysis you can be assured that you are at the right place. See the formatted version of the HTML you have shared and the resolution of the xpath I have provided.
<li class="hasmore drophover"><span>Share & more</span>
<div>
<ul>
<li><button class="tooltip" tip="Use a customizable report creator that can<br>output HTML, CSV, or a shareable link." id="share_on_ajax_result_table">Modify & Share Table</button></li>
<li><button class="tooltip" tip="Get a bit of widget code to emed this table on your site">Embed this Table</button></li>
<li><button class="tooltip" tip="Convert the table below to comma-separated values<br>suitable for use with excel">Get as Excel Workbook (experimental)</button>
<a id="dlink" style="display: none;"></a>
</li>
<li><button class="tooltip" tip="Export table as <br>suitable for use with excel">Get table as CSV (for Excel)</button></li>
<li><button class="tooltip" tip="">Strip Mobile Formatting</button></li>
<li><a id="a_ajax_result_table" name="ajax_result_table" href="#ajax_result_table::none">Copy Link to Table to Clipboard</a></li>
<li><button class="tooltip" tip="">About Sharing Tools</button></li>
<li><button class="tooltip" tip="">Video: SR Sharing Tools & How-to</button></li>
<li><button class="tooltip" tip="">Video: Stats Table Tips & Tricks</button></li>
</ul>
</div>
</li>
So the result you have seen is pretty correct. Now, for you understanding I have inserted some text as MyLink within the intended tag :
<a id="dlink" style="display: none;"></a>
Converted as :
<a id="dlink" style="display: none;">MyLink</a>
See the result :
Check out my solution once again I can ensure that works.
Update B
unable to locate element is good message to debug perhaps apart from "display: none;" you have pulled a rug over the actual issue by mentioning clicked on the share&more link in the first place and found it working. Troubles come up when i try to initiate a click on the link.
If you observe the HTML the element is within class="tooltip" so you need to induce a waiter as follows :
//perform click on the link Share&more
Get_as_Excel_Workbook_link = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//li[#class='hasmore drophover']//ul//li//a[#id='dlink']")))
driver.execute_script("arguments[0].removeAttribute('style')", Get_as_Excel_Workbook_link)
Get_as_Excel_Workbook_link.click()