Selenium cannot locate element - python

I am using selenium to create a kahoot bot flooder. (kahoot.it) I am trying to use selenium to locate the input box, as well as the confirm button. Whenever I try to define them as a variable, I get this. "Command raised an exception: TimeoutException: Message:", which I think means that the 5 seconds that I set has expired, meaning that the element was never located.
for idr in tabs:
num+=1
drv.switch_to.window(idr)
time.sleep(0.3)
gameid = WebDriverWait(drv,5).until(EC.presence_of_element_located((By.CLASS_NAME , "sc-bZSQDF bXdUBZ")))
gamebutton = WebDriverWait(drv,5).until(EC.presence_of_element_located((By.CLASS_NAME , "sc-iqHYGH eMQRbB sc-geEHAE kTTBHH")))
gameid.send_keys(gamepin)
gamebutton.click()
time.sleep(0.8)
try:
nick = WebDriverWait(drv,5).until(EC.presence_of_element_located((By.CLASS_NAME , "sc-bZSQDF bXdUBZ")))
nickbutton = WebDriverWait(drv,5).until(EC.presence_of_element_located((By.CLASS_NAME , "sc-iqHYGH eMQRbB sc-ja-dpGc gYusMa")))
nick.send_keys(f'{name}{num - 1}')
nickbutton.click()
except:
I tried locating an "Iframe" which wasn't really successful (might have done it wrong), but I have been searching for hours and haven't found any answers. Any help would be appreciated.

The Class name for the input and button tags have spaces in it.
For input tag you can use the name attribute. and for button tag you can use the tag name since its the only button tag in the DOM.
gameinput = wait.until(EC.presence_of_element_located((By.NAME,"gameId")))
gameinput.send_keys("Sample Text")
submit = wait.until(EC.presence_of_element_located((By.TAG_NAME,"button")))
submit.click()
#It also worked with below line:
gameinput = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,".sc-bZSQDF.bXdUBZ")))

Related

scraping a page that updates using python selenium

It has now been weeks that I was trying to scrape all the information in this website. This website is the profile of a company and I'm tying to get all the information in this id = "profile-basic" section and id="profile-addresses" section.
I am looping through 1000 0f these profiles and this is only one of them. The reason why Im not showing the code is because its very basic and it will not effect my question, though for the ones that want to know its just a simple for loop that goes through a list one by one.
The problem is a lot of the elements in the page don't appear in some profile but in other profiles they will. I tried solving that by writing down the xpath of all possible elements and than using try: to check all of them and it worked just find, the only problem was the xpath would not always be for one part of information for example the xpath for addres //*[#id="profile-addresses"]/div/div/div/div[1]/p but sometimes it could be //*[#id="profile-addresses"]/div/div/div/div[2]/p many other xpaths. Since im trying to put the address inside the address variable it will be impossible to tell which xpath will be for the address in that page.
I tried using this code:
names = {"آدرس تولیدی :" : "Address", "آدرس دفتر :" : "Address", "تلفن :" : "Phone2",
"تعداد پرسنل :" : "StaffNumber", "کدپستی :" : "PostalCode", "توضیحات :" :
"Description2"}
try:
e=browser.find_element(By.XPATH, '//*[#id="profile-addresses"]/div/div/div/div[1]/span').text
_1 = names.get(e)
__1 = browser.find_element(By.XPATH, '//*[#id="profile-addresses"]/div/div/div/div[1]/p').text
exec(f"global {_1}\n{_1} = Smalify('{__1}')")
except:
pass
try:
e=browser.find_element(By.XPATH, '//*[#id="profile-addresses"]/div/div/div/div[2]/span').text
_2 = names.get(e)
__2 = browser.find_element(By.XPATH, '//*[#id="profile-addresses"]/div/div/div/div[2]/p').text
exec(f"global {_2}\n{_2} = Smalify('{__2}')")
except:
pass
try:
e=browser.find_element(By.XPATH, '//*[#id="profile-addresses"]/div/div/div/div[3]/span').text
_3 = names.get(e)
__3 = browser.find_element(By.XPATH, '//*[#id="profile-addresses"]/div/div/div/div[3]/p').text
exec(f"global {_3}\n{_3} = Smalify('{__3}')")
except:
pass
try:
e=browser.find_element(By.XPATH, '//*[#id="profile-addresses"]/div/div/div/div[4]/span').text
_4 = names.get(e)
__4 = browser.find_element(By.XPATH, '//*[#id="profile-addresses"]/div/div/div/div[4]/p').text
exec(f"global {_4}\n{_4} = Smalify('{__4}')")
except:
pass
try:
e=browser.find_element(By.XPATH, '//*[#id="profile-addresses"]/div/div/div/div[5]/span').text
_5 = names.get(e)
__5 = browser.find_element(By.XPATH, '//*[#id="profile-addresses"]/div/div/div/div[5]/p').text
exec(f"global {_5}\n{_5} = Smalify('{__5}')")
except:
pass
The code above will read the span in front of the main element, and than find the matching variable name from the names dictionary and when it did it will se the value of the main element to the variable name using the exec() function.
This code did not work at all for two reasons, A: It always returned Noun even if it could find the elements. B: It took way too long.
I was wondering if there is anyways other than my code to do it efficiently.
You can always try to search by ID, rather than xpath. Since the xpath is variable between the pages, try to find something that is static, such as ID name.
There is some more information about the different ways you can locate specific html elements using selenium at this link. I definitely recommend checking it out.
Here is an example of searching for your elements by their IDs:
browser.find_element(By.ID, "profile-addresses").text
Good luck!

scraping not working - InvalidSelectorException: Message: invalid selector: An invalid or illegal selector was specified

I am trying to scrape the yahoo finance webpage (comment section). I want to click on a button whose class is seen in the picture below:
I want to select the button with the following code, but I am getting an InvalidSelectorException. I do not understand why.
Note that in my code I have replaced the space with . because that's what I usually do, but I have also tried without replace the spaces and in both cases it is not working.
link = 'https://finance.yahoo.com/quote/AMD/community?p=AMD'
path = r"""chromedriver.exe"""
driver = webdriver.Chrome(executable_path=path)
driver.get(link)
driver.find_element_by_class_name('sort-filter-button.O(n):h.O(n):a.Fw(b).M(0).P(0).Ff(i).C(#000).Fz(16px)')
You can check the below
#This page is taking more time to load
sleep(15)
element = driver.find_element_by_xpath("//button[#aria-label='Sort Reactions']")
element.click()
update
element = driver.find_element_by_xpath("//button[contains(#class,'sort-filter-button')]")
element.click()

Clear search bar using selenium

Im using selenium to check if FB pages exist. When i enter the page title in the search bar it works fine but after the second loop the name of the page gets attached to the preview search and i cant find a way to clear the previous search.
For example it looks for
xyz for the first time
then it looks for
xyzabc when i just want to look for abc this time.
How can i clear the search bar so i can just enter the input without the previous input?
Here is my code
for page_target in df.page_name.values:
time.sleep(3)
inputElement = driver.find_element_by_name("q")
inputElement.send_keys(page_target)
inputElement.submit()
time.sleep(5)
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser').get_text()
title = soup.find(page_target)
#if page exists add 1 to the dic otherwise -1
if title > 0:
dic_holder[page_target] = 1
else:
dic_holder[page_target] = -1
driver.find_element_by_name("q").clear()
time.sleep(3)
You can use
WebElement.clear();//to clear the previous search item
WebElement.sendkeys(abc);//to insert the new search
Also I guess you have a sticky search in your application hence I recommend you to use this method everytime you insert something in the searchbox
Few ways to do it:
Use element.clear(). I see that you already tried in your code, not sure how it didn't work but I guess it is not text box or input element?
Use javascript: driver.execute_script('document.getElementsByName("q")[0].value=""');
Emulate Ctrl+A?
from selenium.webdriver.common.keys import Keys
elem.send_keys(Keys.CONTROL, 'a')
elem.send_keys("page 1")

sending message on youtube live chat with selenium using python

I was trying to make a script using python and selenium, to spam a massage on youtube live stream for a giveaway, i was able to do most of the task successfully until on line (33), where i was trying to locate the youtube live chat box by(.find_element_by_...?) it was showing all kind of error like,AttributeError: 'WebDriver' object has no attribute or failed to locate element_by_...? 'find_element_by_text,xpath,id.class, etc
from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys
email = ''
password = ''
gmail_link = 'http:\\www.gmail.com'
driver = webdriver.Firefox('D:\Projects\python projects')
driver.get(gmail_link)
time.sleep(4)
#email send_keys
driver.find_element_by_id('identifierId').send_keys(email)
#Email_next button xpath.click
driver.find_element_by_xpath('/html/body/div[1]/div[1]/div[2]/div[2] /div/div/div[2]/div/div[2]/div/div[1]/div/content/span').click()
time.sleep(4)
#password xpath
driver.find_element_by_xpath('/html/body/div[1]/div[1]/div[2]/div[2]/div/div/div[2]/div/div[1]/div/form/content/section/div/content/div[1]/div[1]/div/div/div/div/div[1]/div/div[1]/input').send_keys(password)
time.sleep(2)
#password button xpath.click
driver.find_element_by_xpath('/html/body/div[1]/div[1]/div[2]/div[2] /div/div/div[2]/div/div[2]/div/div[1]/div/content/span').click()
time.sleep(5)
#A random youtube live link
driver.get('https://www.youtube.com/watch?v=VTqTnbe6b1g')
time.sleep(5)
# youtube live chat box
driver.find_element_by_text('Say somthing...').send_keys('#PUBGMOBILE')
time.sleep(3)
# youtube live chat box button
driver.find_element_by_id('//*[#id="button"]').click()
Basically that div is associated with 'input' event so you have to dispatch the 'input' event once you enter the value in the div.
Here is the code which I was able to execute successfully form console (FYI this is JS you can use the same logic in your test and language).
ele = document.querySelector('div#input')
ele.textContent = 'test this sample data'
ele.dispatchEvent(new Event('input',{'bubles':true, 'cancelable':true}))
Line 1 is equals findelemnt by css
Line 2 enter the input
Line 3 fireevent 'input' on the element
WebElement chatEle = driver.find_element(By.CSS_SELECTOR('div#input')
chatEle.sendKeys "sample data"
driver.fireEvent(chatEle,"input")
should do the magic, couldn't test the code above as I don't have eclipse java environment on my machine. Test it and let us know.
Refer to Selenium FireEvent document for more information on the fireevent implementation.
Instead of looking for the element by its text you could use its xpath like you did before. I just looked at the chatbox for a YT livestream and the xpath seems to be called //*[#id="input"]
Edit:
Also, there could be something tricky where you need to click the element first before you can enter text.
don't use the [#id="input"] it was also given for another element too. You will not get the element. Use class name {yt-live-chat-text-input-field-renderer style-scope} this is unique you will get the element by this class name.
Your sending text to a wrong element
driver.find_element_by_text('Say somthing...').send_keys('#PUBGMOBILE')
This is lable not a textbox.

How can I click confirm window using selenium

I want to click confirm window using selenium.
So I tried this code
if driver.find_element_by_class_name('sa-confirm-button-container') == True:
no_map.click()
else:
source = driver.page_source
bs = bs4.BeautifulSoup(source,'lxml')
price_list.append(bs.select('#infoJiga'))
I want to know is there 'sa-confirm-button-container' class in html source.(This means there is confirm window.)
If there is class name in source, I want to click confirm-box.
Can you help me?
Please check
if len(driver.find_elements_by_class_name('sa-confirm-button-container'))>0
if driver.find_element_by_class_name('sa-confirm-button-container') == True
this won't work.
Why not just:
try:
element = driver.find_element_by_class_name('sa-confirm-button-container')
except NoSuchElementException:
print('oops, no element')

Categories