Inserting time delays between send_keys requests in Selenium webdriver - python

My initial problem is that when I get the page_source of a website page that I want to scrape, I don't have access to all the code because the full code only loads if I scroll through the different boxes on the site.
I decided to use the send_keys method in Selenium to press the "TAB" key multiple times to go through all the elements on the website page and to load the full code.
But when using the following, the "TAB" key is pressed to rapidly, so the code does not load:
browser.find_element(by=By.ID,value='multi-selector-checkbox-ember44').send_keys(Keys.TAB * 500)
I tried using a time.sleep function to add time delays between each send_keys(Keys.TAB) repetition, but it does not work.

Actually, I found a solution: on the page website, there are buttons of class 'small-input' at every level, so I used this function to scroll down the page:
def scroll_down(self):
to_explore = browser.find_elements(by=By.CLASS_NAME,value='small-input')
for i in range(len(to_explore)):
to_explore[i].send_keys((Keys.TAB)*2)
time.sleep(.5)

Related

Python Selenium, edge browser, I dont see Inspect Element on every element

I am trying to get data from a Power Bi table. There are some elements that appear when hovering over a table. When I right click on ... I don't see Inspect Element. However, when I left click on this element, I can see a menu, and if I right click on any items, I can see Inspect element.
My first question, is why I don't see Inspect Element in the right click menu for all elements in the browser. Am I somehow able to open this ... menu programmatically in Selenium?
the Export Data element only appears in HTML after the first left click. I'm assuming this is created using Javascript and in order to export data with Selenium I would have to programmatically instantiate this by clicking on the ... menu. Is selenium capable of triggering javascript functions that generate more html code in a dynamic webpage? Or do I need to somehow click on the ... element.
If I can execute a javascript function, how can I find out in Edge the javascript function that gets executed and how can I replicate this function in Selenium
Essentially, if I try to find the Export data element in Selenium, it is not able to find it, unless I set a breakpoint before search, then in EdgeDriver I open this menu, and then I can find it and click it through Python
If all else fails, can I programmatically open the left click menu by automating a mouse click at certain coordinates in Selenium?
1.1 why I don't see Inspect Element in the right click menu for all elements:
PowerBi has its own context menu so they suppress the browsers context menu. If the element is tricky to find the dev tools, you can press Ctrl + Shift + C (while dev tools is open) and then click the desired element. Your mouse needs to be already over the element before pressing the key combination.
1.2 Am I somehow able to open this ... menu programmatically in Selenium?
Seems a little tricky, but could work if you first find the title of that area and move the mouse there, like described here: https://stackoverflow.com/a/8261754/12914172
Then your element should be in the html and you can find it hopefully by its class name vcMenuBtn that seems to be unique on that page. But you need to verify that.
2. Is selenium capable of triggering javascript functions that generate more html code in a dynamic webpage? Or do I need to somehow click on the ... element.
Selenium is able to execute javascript like desribed here: https://stackoverflow.com/a/70544802/12914172
However in your sample, and I was quickly checking the PowerBI online page, this looks like a whole lot of reverse engineering to understand and can sometimes be dangerous as well. I would go for hoover over the area find the ... and click it.
3. How can I find out in Edge the javascript function that gets executed
In dev tools you can set breakpoints to debug the steps the pages does after an action. But again, I would not invest to much time in that.
4. Can I programmatically open the left click menu by automating a mouse click at certain coordinates in Selenium?
Yes but this never works as good as the way described above. If you still want to give it a try, maybe that answer helps: https://stackoverflow.com/a/26385456/12914172
Many thanks to r000bin, this solution works for me, downloading data from PowerBI using Selenium for Python:
import selenium, mouse, time
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
url = 'https://dataport.gasunie.nl/Vulling-Gasopslagen-Nederland'
driver = selenium.webdriver.Chrome(service=Service())
driver.get(url)
time.sleep(4)
#driver.fullscreen_window()
#driver.switch_to.window(driver.current_window_handle)
time.sleep(4)
iframe = driver.find_elements(By.TAG_NAME, 'iframe')
assert len(iframe)==1
driver.switch_to.frame(iframe[0])
time.sleep(4)
from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)
actions.move_to_element_with_offset(driver.find_element(By.TAG_NAME, 'html'), 0,0)
actions.move_by_offset('5', '5').click().perform()
time.sleep(4)
button = driver.find_element(By.CLASS_NAME, 'vcMenuBtn')
button.click()
button = driver.find_element(By.ID, '0')
button.click()
# 4 tabs and 1 enter
time.sleep(4)
for n in range(4):
element = driver.switch_to.active_element
time.sleep(2)
element.send_keys(Keys.TAB)
time.sleep(2)
element = driver.switch_to.active_element
time.sleep(2)
element.send_keys(Keys.ENTER)
driver.close()

Click button with Selenium webdriver for Python does not work in function

I'm trying to do some web scraping for products. In this particular page, there is a "More Products" button, which I built a function to click as many times as needed to load all the products for my respective filter.
When I simply use like this, it works perfectly:
driver.find_element_by_class_name('cf-load-more').click()
But if I try to use it inside a function:
def pushButton(qty):
pushes = math.ceil(qty/20) #20 products are displayed each time
for p in range(pushes+1):
driver.find_element_by_class_name('cf-load-more').click()
time.sleep(5)
it results in this error, saying that the button is not clickable:

Selenium script is not consistent

I have other examples, but for this specific example what the code does is locate a series of elements that each link to a specific page. Then I click on a specific link. Sometimes this code works, but sometimes it does not work and the page just stays the same without clicking on the link.
I have used a variety of methods like sleep, wait and ActionChains in an attempt to make things more consistent, but it still messes up really frequently.
print(f"No.{i} Opportunity found {optitle_list[i]}")
#click on tender
time.sleep(10)
opentender_button =WebDriverWait(driver,30).until(EC.visibility_of_all_elements_located((By.XPATH,"//img[#src = 'esources/theme/images/view.png']")))
ActionChains(driver).move_to_element(opentender_button[int((j-3)/10)]).double_click().perform()
Here is another example. In this code the keys 'health' are not always sent, resulting in the wrong search options being reviewed by my script.
#Enter into Search box ‘health' and hit "Enter" key
time.sleep(20)
search_box = WebDriverWait(driver,30).until(EC.element_to_be_clickable((By.XPATH,"//label//input[#type='text']")))
ActionChains(driver).move_to_element(search_box).double_click(search_box).send_keys('health').perform()
print("Search box filled")

Scraping Instagram followers for an account

I'm trying to scrape followers from an Instagram account by using Selenium. (https://www.instagram.com/france/followers/)
I need to scroll down a popup page but the only thing I can scrolldown is the back page.
Here is my code
scr1 = driver.find_element_by_xpath('/html/body/div[4]/div/div')
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);",scr1) ## Scroll to bottom of page with using driver
I also tried in my JS browser console by using the JSPath of my dialog modal :
window.scrollTo(0, document.querySelector("body > div.RnEpo.Yx5HN > div"));
(Already saw Stack posts related but answers seems deprecated in Oct. 2020)
I've had similar issues with what you are trying to do. Currently, the method I have implemented in my script uses Selenium's ActionChains class which I find is much more helpful than all the Javascript (execute_script) answers out there.
Basically I use ActionChains to press the "down" arrow key and then manipulate it to my advantage. I'll lay out the basic syntax below:
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(browser)
actions.send_keys(Keys.DOWN).perform() #sends a general down arrow key to the page
Now I focus the ActionChains on a specific element, in this case it's the popup. There's a ton of ways to focus on the element but I find the easiest workaround is simply clicking the element before using ActionChains
Like this:
popup = driver.find_element_by_class_name('popupClass') #you don't have to use class_name
for i in range(500): #500 is amount of scrolls
popup.click() #focus the down key on the popup
actions.send_keys(Keys.DOWN).perform() # press the down key
The above method will click on the popup and then press the down key once, essentially sending 500 "scrolls" to the popup rather than the whole page. Once it's done, you're gonna wanna grab the .text property on the element responsible for the popups (at least that's what I did in my script).

How do I loop through these web pages with selenium?

I am new to programming but am getting familiar with web-scraping.
I wish to write a code which clicks on each link on the page.
In my attempted code, I have made a sample of just two links to click on to speed things up. However, my current code is only yielding the first link to be clicked on but not the second.
from selenium import webdriver
import csv
driver = webdriver.Firefox()
driver.get("https://www.betexplorer.com/baseball/usa/mlb-2018/results/?
stage=KvfZSOKj&month=all")
matches = driver.find_elements_by_xpath('//td[#class="h-text-left"]')
m_samp = matches[0:1]
for i in m_samp:
i.click()
driver.get("https://www.betexplorer.com/baseball/usa/mlb-2018/results/?
stage=KvfZSOKj&month=all")
Ideally, I would like it to click the first link, then go back to the previous page, then click the second link, then go back to the previous page.
Any help is appreciated.
First take the all the clickable urls into one list
then iterate list
like list_urls= ["url1","url2"]
for i in list_urls:
driver.get(i)
save the all urls other wise going back and clicking will not work , because the you have only one instance of driver not the multiple

Categories