How to get current iframe reliably next time program is run? - python

I'm using the below code to get the current element at a cursor position, even if that element is within several iframes. I have two questions though.
Are all iframes located within an "iframe" tag as would be needed for the below code to work? If not, is there a more accurate way to do what I'm trying to do below?
How can I define the current iframe so that I can reliably return that identifier and find the same iframe next time the program is run? The element ID and session ID change each time the program is run, so if I were to manually save the iframe and use it to driver.switch_to.frame(element) next time the program ran, I know it wouldn't find it. So how can I make sure I'm in the correct iframe when locating an element after finding it this way?
Edit: To clarify, I'm attempting to create a script that works universally with any website, so the HTML of the website in this code would not be useful to include. That's why I wanted to know if all websites with iframes must use an "iframe" tag, or if there are some websites that this approach wouldn't work?
from selenium import webdriver
from tkinter import *
from pynput import mouse
from pynput.mouse import Listener
import time
def CheckRightClick(x, y, button, pressed):
if button == mouse.Button.right:
if pressed:
# Browser window position calculation script
coordinate_script = """
var X, Y;
if (window.screenY)
{
X = window.screenX;
Y = window.screenY + 124;
}
else
{
var Elem = document.documentElement;
if (!Elem.clientHeight) Elem = document.body;
X = Elem.scrollLeft;
Y = Elem.scrollTop;
}
return new Array(X, Y);
"""
print('Getting element')
driver.switch_to.default_content()
winPos = driver.execute_script(coordinate_script)
# actual element position in browser
x -= winPos[0]
y -= winPos[1]
driver.implicitly_wait(30)
element = driver.execute_script("""
return document.elementFromPoint(arguments[0], arguments[1]);
""", x, y)
# element = findElement(x, y)
deepestElement = None
if element is None:
print('current cursor position might be wrong')
return
if element is not None:
print(" id=> ", element.get_attribute("id"), "\n tagName=> <", element.tag_name, ">", "\n text=> ", element.text, "\n\r")
if element.tag_name == "iframe":
# get iframe element position. it will return {top: , left:, x: , y: , width: , height}
elementPos = driver.execute_script("""
var element = document.elementFromPoint(arguments[0], arguments[1]);
if(element !== null)
return element.getBoundingClientRect();
else
return null;
""", x, y)
# actual element postion in the iframe.
x -= elementPos['left']
y -= elementPos['top']
driver.switch_to.frame(element)
deepestElement = driver.execute_script("""
return document.elementFromPoint(arguments[0], arguments[1]);
""", x, y)
else:
deepestElement = element
if deepestElement is not None:
print("deepest element:\n id=> ", deepestElement.get_attribute("id"), "\n tagName=> <", deepestElement.tag_name, ">", "\n text=> ", deepestElement.text, "\n\r")
print('Element at cursor is ', deepestElement, "\n\r")
#deepestElement.click()
# click_window.event_generate("<<quit>>")
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
# driver = webdriver.Chrome(options=options, executable_path=r'./chromedriver_90.exe')
driver = webdriver.Chrome(options=options,executable_path=r'C:\Users\David\Desktop\Python\chromedriver_win32'r'\chromedriver.exe')
url = 'http://store.cardsagainsthumanity.com/'
driver.get(url)
time.sleep(3)
click_window = Tk()
click_prompt = Label(click_window, text='Right click somewhere')
click_prompt.grid(row=3, column=3)
click_window.bind("<<quit>>", lambda *args: click_window.destroy())
listener = Listener(on_click=CheckRightClick)
listener.start()
click_prompt.mainloop()
listener.stop()

Related

The executable python file outputs fatal error message

I have written a python script that communicates with the web page and makes an online order. In addition to that I have added some GUI, which allows the user to select the day of the order. Here is the python script
import easygui
import sys
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
import tkinter as tk
import tkinter.font as tkFont
badge_number = 111111
# Widget pop up for selection of the order day
root = tk.Tk()
def center_window(w=300, h=200):
# get screen width and height
ws = root.winfo_screenwidth()
hs = root.winfo_screenheight()
# calculate position x, y
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
root.geometry("400x450")
Label = tk.Label(root, text = "Select lunch Order Day", font = ("Helvetica", 15))
Label.pack(pady=50, padx=40)
helv15 = tkFont.Font(family = "Helvetica", size = 15)
root.lift()
v = tk.StringVar()
v.set("Today")
tk.Label(root, textvariable = v).pack()
def close_window():
root.destroy()
today = tk.Radiobutton(root, text = "Today", variable = v, value = "Today", font = helv15).pack()
tomorrow = tk.Radiobutton(root, text = "Tomorrow", variable = v, value = "Tomorrow", font = helv15).pack()
cancel = tk.Radiobutton(root, text = "Cancel", variable = v, value = "Cancel", font = helv15).pack()
submit = tk.Button(root, text = "Submit", command = close_window, font = helv15).pack()
center_window(400, 400)
root.mainloop()
if v.get() == "Cancel":
sys.exit("Ordering was terminated")
driver = webdriver.Chrome(executable_path = "C:\webdrivers\chromedriver.exe")
driver.get("http://web_page/")
element = driver.find_element_by_name('employee_id')
element.send_keys(badge_number)
driver.find_element_by_xpath("/html/body/section/header/form/div/button").click()
# /html/body/section/header/form/div/button
delay = 60
todayBut = "/html/body/section/div[1]/div[2]/div/div/div/span[2]/span[1]/form/button"
tomorBut = "/html/body/section/div[1]/div[2]/div/div/div/span[1]/span[1]/form/button"
favorButToday = "/html/body/section/div/div[1]/button"
favorButTomor = "/html/body/section/div/div[1]/button/a"
myFavOrderID = "fav_order_view"
try:
element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, todayBut)))
except TimeoutException:
print ("Loading Day Selection page took too much time!")
if v.get() == "Today":
driver.find_element_by_xpath(todayBut).click()
#favorite choice
try:
element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, favorButToday)))
driver.find_element_by_xpath(favorButToday).click()
try:
element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.ID, myFavOrderID)))
driver.find_element_by_id(myFavOrderID).click()
### select floor, order date and order now
select_floor = Select(driver.find_element_by_name("floor_number"))
select_floor.select_by_index("9")
select_day = Select(driver.find_element_by_name("order_date"))
select_day.select_by_value("today")
orderNowBtn = "/html/body/div[1]/div[2]/div/div/div[3]/form/button"
driver.find_element_by_xpath(orderNowBtn).click()
print("Today's order was successfully made!")
except TimeoutException:
print ("Loading Favorites page took too much time!")
except TimeoutException:
print ("Loading took too much time!")
else:
driver.find_element_by_xpath(tomorBut).click()
#favorite choice
try:
element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, favorButTomor)))
driver.find_element_by_xpath(favorButTomor).click()
try:
myFavOrderIDTomor = "fav_order_view"
element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.ID, myFavOrderIDTomor)))
driver.find_element_by_id(myFavOrderIDTomor).click()
### select floor, order date and order now
select_floor = Select(driver.find_element_by_name("floor_number"))
select_floor.select_by_index("9")
select_day = Select(driver.find_element_by_name("order_date"))
select_day.select_by_value("tomorrow")
orderNowBtnTomor = "/html/body/div[1]/div[2]/div/div/div[3]/form/button"
driver.find_element_by_xpath(orderNowBtnTomor).click()
print("Tomorrow's order was successfully made!")
except TimeoutException:
print ("Loading Favorites page took too much time!")
except TimeoutException:
print ("Loading took too much time!")
However, I wanted to have it as an .exe file to run it with just double-click from my desktop. So, I have installed pyinstaller from git and run the simple line in the cmd (pyinstaller.exe --onefile --windowed --icon=app.ico LunchOrder.py). Unfortunately, the .exe isn't doign anything, it just pops up the "Fatal error detected" message, without any GUI (that I have written into the script itself). Any help would be appreciated!
Here i will tell you a better way to make .py to .exe . First make sure your python is added to system PATH, which i assume is. If not check some tutorials on how to add python to PATH then you can open your cmd and type in:
pip install pyinstaller
After this, you go to your path where the LunchOrder.py exists and open a cmd there, in windows you can type simply type in cmd in the address bar (after clearing adressbar), or else open a cmd and navigate to your path where LunchOrder.py file exists and simply type in:
pyinstaller -w -F -i "app.ico" LunchOrder.py
This should make a folder dist inside which your .exe will be there. MAKE SURE TO COPY THE .exe to outside the dist folder and run it there. Or else you might still get fatal error message. You can delete all the other extra files that was generated like build and LunchOrder.spec . If it still gives you error try following this method https://www.youtube.com/watch?v=OZSZHmWSOeM

Python Selenium - browser.find_element_by_class_name - returns error SOMETIMES?

I'm a newB to Python - going through "Automate the Boring Stuff" - Al Swigart.
I've written a script to play the "2048" tile game at "https://gabrielecirulli.github.io/2048". After several moves, the tile game will "max out" and pop up a "Game Over!" which I haven't figured out how to read - so instead I've implemented logic to read the score after a series of every 4 moves, figure out if the score has stopped increasing, and if so, Game Over!
What I'm finding is my statement to read the score, is returning an error sometimes. I can't figure out why it either just works, or doesn't. Why does it return an error, sometimes?!?
I put it in a try/except block, so if I get an error, I count it up. Sometimes it's a few, sometimes it's about half the time.
I'd appreciate any help or suggestions.
Thanks.
output...
Evolutions: 40 oldScore1308 newScore: 1736
Evolutions: 41 oldScore1736 newScore: 1736
GAME OVER!
Good Game.
Final Score:
Evolutions: 41 OldScore1736 NewScore: 1736 Errors:23
Pausing before program closes. Hit enter to continue.
Code:
#! python
import webbrowser
from selenium import webdriver
from selenium.webdriver.common.keys import Keys # import Keys to send special keys
from selenium.common.exceptions import NoSuchElementException
import time
def opensite():
# open browser
global browser # stop chrome window from closing by itself.
browser = webdriver.Chrome()
browser.get("https://gabrielecirulli.github.io/2048")
return browser
def botKeys():
# function to send arrow keys to browser :up, right, down, left.
w = 0.025 # time to wait between plays
try:
element = browser.find_element_by_tag_name("body")
gameOn = True
counter = 0
oldScore = 0
error = 0
while gameOn == True:
counter += 1
# Send keys to move pieces
time.sleep(w)
element.send_keys(Keys.UP)
time.sleep(w)
element.send_keys(Keys.RIGHT)
time.sleep(w)
element.send_keys(Keys.DOWN)
time.sleep(w)
element.send_keys(Keys.LEFT)
# check the score. Keep track of it to determine if GAME OVER!
try:
newScore = browser.find_element_by_class_name(
"score-container"
) # get the object with the score.
newScore = int(
newScore.text
) # read the text of the object, which is the score in a string. Convert it to an integer.
print(
f"Evolutions: {counter} oldScore{oldScore} newScore: {newScore}"
)
if oldScore != newScore:
oldScore = newScore
else: # old and new are the same, game over
print(f"GAME OVER!\nGood Game.")
print(f"\nFinal Score:")
print(
f"Evolutions: {counter} OldScore{oldScore} NewScore: {newScore} Errors:{error}"
)
gameOn = False
except ValueError:
error += 1 # count value errors, but that's all.
except NoSuchElementException:
print("Could not find element")
input("Pausing before program closes. Hit enter to continue.")
def main():
# TODO open the site
driver = opensite()
# TODO send keystrokes
botKeys()
driver.close()
if __name__ == "__main__":
main()
If you display error
except ValueError as ex:
error += 1
print(ex)
then you see what is the problem
invalid literal for int() with base 10: '3060\n+20'
Problem is that sometimes it displays result 3060 with points which it adds to result +20.
It works correctly when you split it on \n and get first elements
newScore = int(
newScore.text.split('\n')[0]
)
To recognize Game Over you need
game_over = driver.find_element_by_class_name("game-over") #
but it raises error when there is no class game-over so I would use find_elements (with s at the end of word find_elements) to get empty list instead of rasing error.
BTW: I changed some names because PEP 8 -- Style Guide for Python Code
from selenium import webdriver
from selenium.webdriver.common.keys import Keys # import Keys to send special keys
from selenium.common.exceptions import NoSuchElementException
import time
def opensite():
driver = webdriver.Chrome()
driver.get("https://gabrielecirulli.github.io/2048")
return driver
def bot_keys(driver):
'''Function to send arrow keys to browser :up, right, down, left.'''
wait = 0.025 # time to wait between plays
try:
element = driver.find_element_by_tag_name("body")
game_on = True
counter = 0
old_score = 0
new_score = 0
error = 0
while game_on:
counter += 1
# Send keys to move pieces
time.sleep(wait)
element.send_keys(Keys.UP)
time.sleep(wait)
element.send_keys(Keys.RIGHT)
time.sleep(wait)
element.send_keys(Keys.DOWN)
time.sleep(wait)
element.send_keys(Keys.LEFT)
# check the score. Keep track of it to determine if GAME OVER!
try:
new_score = driver.find_element_by_class_name("score-container") # get the object with the score.
new_score = int(new_score.text.split('\n')[0]) # read the text of the object, which is the score in a string. Convert it to an integer.
print(f"Evolutions: {counter:5} | Old Score: {old_score:5} | New Score: {new_score:5}")
old_score = new_score
game_over = driver.find_elements_by_class_name("game-over") # get the object with the score.
#print('game_over:', len(game_over))
if game_over:
print("\nGAME OVER!\n")
print("Final Score:")
print(f"Evolutions: {counter:5} | New Score: {new_score:5} | Errors: {error}")
game_on = False
except ValueError as ex:
print('ex:', ex)
error += 1 # count value errors, but that's all.
except NoSuchElementException:
print("Could not find element")
input("\nPausing before program closes. Hit enter to continue.")
def main():
driver = opensite()
bot_keys(driver)
driver.close()
if __name__ == "__main__":
main()
Maybe next step would be to use Gym (or something similar) to use Reinforcement Learning (Machine Learning, Artificial Intelligence)
Looks good! Here's my solution:
'''
2048
2048 is a simple game where you combine tiles by sliding them up, down,
left, or right with the arrow keys. You can actually get a fairly high score
by repeatedly sliding in an up, right, down, and left pattern over and over
again. Write a program that will open the game at https://gabrielecirulli
.github.io/2048/ and keep sending up, right, down, and left keystrokes to
automatically play the game.
'''
from selenium import webdriver
import random
import time
import os
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import ElementNotInteractableException
os.makedirs('2048', exist_ok=True)
bestScoreCurrent, check, attempts = 0, False, 0
driver = webdriver.Firefox()
# driver.maximize_window()
driver.get('https://gabrielecirulli.github.io/2048/')
def saveScreenshot(screenshot, filename, best, timeLoc):
filename = f'2048\{best}_{filename}_{timeLoc}.png'
with open(filename, 'wb') as elemFile:
elemFile.write(screenshot)
def tryRetryButton():
gameScreenshot = driver.find_element_by_css_selector(
'.game-container').screenshot_as_png
try:
driver.find_element_by_css_selector('.retry-button').click()
return True, gameScreenshot
except ElementNotInteractableException:
return False, gameScreenshot
def botLogic():
for key in [Keys.UP, Keys.RIGHT, Keys.DOWN, Keys.LEFT]:
bestScorePossible = int(driver.find_element_by_css_selector(
".best-container").text)
time.sleep((random.randint(5, 10) / 20))
userElem = driver.find_element_by_xpath('/html/body')
userElem.send_keys(key)
return bestScorePossible
while True:
bestScorePossible = botLogic()
bestScoreScreenshot = driver.find_element_by_css_selector(
'.best-container').screenshot_as_png
check, gameScreenshot = tryRetryButton()
if check and bestScorePossible > bestScoreCurrent:
attempts += 1
print(
f'New best score {bestScorePossible}! Total attempts {attempts}')
bestScoreCurrent = bestScorePossible
timeLoc = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime())
saveScreenshot(bestScoreScreenshot, 'bestScore', bestScoreCurrent, timeLoc)
saveScreenshot(gameScreenshot, 'bestGameWindow', bestScoreCurrent, timeLoc)

Python Selenium Printing Save-As-PDF Waiting for Filename Input

I'm trying to save a website as PDF through printing dialog. My code allows me to save as pdf, but asks me to input a filename, which I don't know how to pass a filename to the pop up box.
Attached is my code:
import time
from selenium import webdriver
import os
class printing_browser(object):
def __init__(self):
self.profile = webdriver.FirefoxProfile()
self.profile.set_preference("services.sync.prefs.sync.browser.download.manager.showWhenStarting", False)
self.profile.set_preference("pdfjs.disabled", True)
self.profile.set_preference("print.always_print_silent", True)
self.profile.set_preference("print.show_print_progress", False)
self.profile.set_preference("browser.download.show_plugins_in_list",False)
foxdriver = r'C:\Users\AShen\Documents\Workspace\geckodriver.exe'
self.driver = webdriver.Firefox(executable_path=foxdriver,firefox_profile = self.profile)
time.sleep(5)
def get_page_and_print(self, page):
self.driver.get(page)
time.sleep(5)
self.driver.execute_script("window.print();")
if __name__ == "__main__":
browser_that_prints = printing_browser()
browser_that_prints.get_page_and_print('http://www.google.com/')
These days I had the same question.
I solved it without using the pyautogui in these case, because I use different PCs and monitors and I didn't want to depend on the position of the click.
I was able to solve it using the about:config... changing them with each necessary print (in PDF).
The name of my printer "in PDF" in Ubuntu is "Print to File" (defined in print_printer) and the settings of about:config need to be this printer...
For example: print.printer_Print_to_File.print_to_file: true
import os
import time
from selenium import webdriver
class printing_browser(object):
def __init__(self):
self.profile = webdriver.FirefoxProfile()
self.profile.set_preference('services.sync.prefs.sync.browser.download.manager.showWhenStarting', False)
self.profile.set_preference('pdfjs.disabled', True)
self.profile.set_preference('print.always_print_silent', True)
self.profile.set_preference('print.show_print_progress', False)
self.profile.set_preference('browser.download.show_plugins_in_list', False)
self.profile.set_preference('browser.download.folderList', 2)
self.profile.set_preference('browser.download.dir', '')
self.profile.set_preference('browser.download.manager.showWhenStarting', False)
self.profile.set_preference('browser.aboutConfig.showWarning', False)
self.profile.set_preference('print.print_headerright', '')
self.profile.set_preference('print.print_headercenter', '')
self.profile.set_preference('print.print_headerleft', '')
self.profile.set_preference('print.print_footerright', '')
self.profile.set_preference('print.print_footercenter', '')
self.profile.set_preference('print.print_footerleft', '')
self.profile.set_preference('browser.helperApps.neverAsk.saveToDisk', 'application/octet-stream;application/vnd.ms-excel;text/html')
foxdriver = r'C:\Users\AShen\Documents\Workspace\geckodriver.exe'
self.driver = webdriver.Firefox(
executable_path=foxdriver,
firefox_profile=self.profile
)
time.sleep(1)
def get_page_and_print(self, page, filepath):
# Get about:config
self.driver.get('about:config')
time.sleep(1)
# Define Configurations
script = """
var prefs = Components.classes['#mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefBranch);
prefs.setBoolPref('print.always_print_silent', true);
prefs.setCharPref('print_printer', 'Print to File');
prefs.setBoolPref('print.printer_Print_to_File.print_to_file', true);
prefs.setCharPref('print.printer_Print_to_File.print_to_filename', '{}');
prefs.setBoolPref('print.printer_Print_to_File.show_print_progress', true);
""".format(filepath)
# Set Configurations
self.driver.execute_script(script)
time.sleep(1)
# Get site to print in pdf
self.driver.get(page)
time.sleep(2)
self.driver.execute_script("window.print();")
browser_that_prints = printing_browser()
browser_that_prints.get_page_and_print('http://www.google.com', os.path.join(os.getcwd(), 'mywebpage.pdf'))
Oh, it is very easy if you know about pyautogui.
This is an amazing module that allows you to automate your curser.
So essentially, you need to figure out the place where the popup appears and use pyautogui to click it for you.
All you need to add is:
time.sleep(3)
i=random.randint(0,1000)
file_name=('name_pdf '+str(i))
print (file_name)
pyautogui.typewrite(file_name)
pyautogui.click(512,449)
Entire code structure will look like this:
import time
import pyautogui
from selenium import webdriver
import os
class printing_browser(object):
def __init__(self):
self.profile = webdriver.FirefoxProfile()
self.profile.set_preference("services.sync.prefs.sync.browser.download.manager.showWhenStarting", False)
self.profile.set_preference("pdfjs.disabled", True)
self.profile.set_preference("print.always_print_silent", True)
self.profile.set_preference("print.show_print_progress", False)
self.profile.set_preference("browser.download.show_plugins_in_list",False)
foxdriver = r'C:\Users\Pranjal Pathak\Desktop\Titanic Kaggle\geckodriver.exe'
self.driver = webdriver.Firefox(executable_path=foxdriver,firefox_profile = self.profile)
time.sleep(5)
def get_page_and_print(self, page):
self.driver.get(page)
time.sleep(5)
self.driver.execute_script("window.print();")
if __name__ == "__main__":
browser_that_prints = printing_browser()
browser_that_prints.get_page_and_print('http://www.python.org/')
time.sleep(3)
i=random.randint(0,1000)
file_name=('name_pdf '+str(i))
print (file_name)
pyautogui.typewrite(file_name)
pyautogui.click(512,449)
Note: 1. I have selected the name of the file as name+any random integer between 1 to 1000 to change name every time you save the file. This way it will save every time you run the code as the names will be different every time.
If this types the name but does not save the file, you might want to change the coordinates of your curser. Let me know if that happens.

Copy cell value and paste into search box

I'm trying to design an automation process that reads the value of a cell in an excel document, copies the value into a variable, and that variable is is pasted into a search box on a site. When the process is called again it goes to the next line, gets the new cell value, and searches again. However I can't seem to get it right in the slightest!
*Edit 7/21/2016
My current problem now is that on every iteration of the code the previous cell and new cell values are pasted. For example the first cell is 42-7211 and the second cell is 45-7311 and on the next time the function is called it pastes " 42-721145-7311 " not "45-7311"
Here is my full updated code. Once i get to the proper screen I use the function
prod_choose_searchbar to paste and then call stp to go to the next cell.
My Code UPDATED
import unittest
import xlrd
import os
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium import *
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
from selenium.common.exceptions import NoSuchElementException
from datetime import date
from datetime import timedelta
import time
from time import sleep
def yesterday():
# Get today.
today = date.today()
# Subtract timedelta of 1 day.
yesterday = today - timedelta(days=1)
return yesterday
import logging
#start logging module this will record all actions and record them for debugging purposes!
LOG_FILENAME = 'log_file_selenium.txt'
logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG)
logging.debug('This message should go to the log file')
#clear window
os.system('cls')
#open EXCEL
#Start classes
#define variables to call for automation process
#this will help run faster so the code is shorter in the main sections
"""
Used to read cells from an excel file one at a time
Use:
1) Call the class with new()
2) Call new.var() to clear variables and start at top of document
3) Call new.stp() to begin process
4) Call new.nextp() until finished
"""
#########################################################################
#########################################################################
class calls_sms():
def __init__(self): #sets variables up and inital value NULL
self.w = None
self.variable = None
self.value = None
self.default_int = 0 #
self.default_string = None #These are for empty feilds
self.default = None #
#open EXCEL
self.file_location = "C:\\Users\\doarni\\Desktop\\T0088Transfer.xls"
self.workbook = xlrd.open_workbook(self.file_location)
self.sheet = self.workbook.sheet_by_index(0)
#Excel interaction
def beginprod(self):
self.w = 1
calls_sms.stp(self)
def stp(self):
for row in range(self.sheet.nrows):
row = self.sheet.row_values(self.w)
self.variable = None
self.variable = row[7]
self.w += 1
return row[7]
#abbreviations for later use
def var(self): #must be called var, driver is not defined till launch call
self.xpath = self.driver.find_element_by_xpath
self.classname = self.driver.find_element_by_class_name
self.css = self.driver.find_element_by_css_selector
self.actions = ActionChains(self.driver)
#Open IE driver and new IE window
def launch(self):
self.driver = webdriver.Ie()
self.driver.get("https://www.mywebsite.com/")
logging.debug('Connected to SMS on '+str(date.today())+'')
def login(self):
self.username = self.classname("GJCH5BMD1C")
self.password = self.xpath("//*[#type='password']")
try:
self.username.send_keys("username")
self.password.send_keys("password")
self.log_in = self.xpath("//*[#class='GJCH5BMI-C']").click()
except:
os.system('python sms_generic_err.py')
logging.debug('FAILED LOGIN'+str(date.today())+'')
#Stock tab
def stock_tab(self):
#Only call when on stock tab
self.stock = self.xpath("//div[#class='GJCH5BMHEF' and text()=' Stock ']").click()
time.sleep(0.2)
def stock_tab_prd_select(self):
#opens prod chooser
self.stockselect = self.xpath("//span[#class='GJCH5BMKU' and text()='Select']").click()
def stock_searchbtn(self):
self.stocksearch = self.xpath("//*[#class='GJCH5BMJV']")
self.stocksearch.click()
def stock_tab_prd_clear(self):
#clears product
self.stockclear = self.xpath("//span[#class='GJCH5BMKU' and text()='Clear']").click()
def stock_resetbtn(self):
#stock reset button
self.stockreset = self.xpath("//span[#class='GJCH5BMKU' and text()='Reset']").click()
#Product Chooser
def prod_choose_searchbar(self):
#finds the searchbox and clicks
self.search = self.css(".GJCH5BMASD")
self.search.click()
print('paste value: '+str(self.variable))
#pastes in prod number from variable
self.clicksearch = self.actions.move_to_element(self.search).send_keys(calls_sms.stp(self)).perform()
print('paste value after: '+str(self.variable))
def prod_choose_clicksearch(self):
self.clicksearch = self.xpath("//*[#class='GJCH5BMPR']").click()
def prod_choose_clickadd(self):
self.clickadd = self.css(".GJCH5BMCHI").click()
def prod_choose_clickfinish(self):
self.clickfinish = self.xpath("//div[#class='GJCH5BMJYC GJCH5BMGYC' and text()='Finish']").click()
#these must be called manually in the script not through the class
def user_ask_invtab():
os.system('python sms_err_select_inv.py')
def user_ask_ciinsight():
os.system('python sms_err_select_ciinsight.py')
if __name__ == "__main__":
unittest.main()
#########################################################################
#########################################################################
#Check Territory
#NEEDS TO BE FIXED LATER!
#this will most likely be built in another module
class territory_check():
def check_exists_ci__by_xpath():
try:
webdriver.find_element_by_xpath("//*[#class='GJCH5BMOW']")
except NoSuchElementException:
return False
os.system("python sms_connected_ci.py")
return True
#########################################################################
#########################################################################
SMS = calls_sms()
#%#%#%#%#%#%#%#%#%#%#%#%
SMS.launch()
SMS.var()
SMS.login()
os.system('python sms_err_select_inv.py')
time.sleep(2)
SMS.stock_tab()
time.sleep(2)
SMS.beginprod()
SMS.stock_tab_prd_select()
time.sleep(1)
SMS.prod_choose_searchbar()
time.sleep(2)
SMS.prod_choose_clickfinish()
time.sleep(2)
SMS.stock_tab_prd_select()
time.sleep(1)
SMS.prod_choose_searchbar()
time.sleep(2)
SMS.prod_choose_clickfinish()
time.sleep(1)
SMS.stock_tab_prd_select()
time.sleep(1)
SMS.prod_choose_searchbar()
time.sleep(2)
SMS.prod_choose_clickfinish()
I want it to read the excel file, grab the value from the cell, paste it into send_keys. and then be able to call another function to move to the next cell below and loop only when called.
I figured it out finally. I have to update the actions variable or else the strings are stored in it each time. will post solution soon once its written

Get url from chrome using python

I'm very new to python and I'm trying to print the url of an open websitein Chrome. Here is what I could gather from this page and googeling a bit:
import win32gui, win32con
def getWindowText(hwnd):
buf_size = 1 + win32gui.SendMessage(hwnd, win32con.WM_GETTEXTLENGTH, 0, 0)
buf = win32gui.PyMakeBuffer(buf_size)
win32gui.SendMessage(hwnd, win32con.WM_GETTEXT, buf_size, buf)
return str(buf)
hwnd = win32gui.FindWindow(None, "Chrome_WidgetWin_1" )
omniboxHwnd = win32gui.FindWindowEx(hwnd, 0, 'Chrome_OmniboxView', None)
print(getWindowText(hwnd))
I get this as a result:
<memory at 0x00CA37A0>
I don't really know what goes wrong, whether he gets into the window and the way I try to print it is wrong or whether he just doesn't get into the window at all.
Thanks for the help
Only through win32 can only get the information of the top-level application. If you want to get the information of each component located in the application, you can use UI Automation.
Python has a wrapper package Python-UIAutomation-for-Windows, and then you can get the browser's address bar url through the following code:
import uiautomation as auto
def get_browser_tab_url(browser: str):
"""
Get browser tab url, browser must already open
:param browser: Support 'Edge' 'Google Chrome' and other Chromium engine browsers
:return: Current tab url
"""
if browser.lower() == 'edge':
addr_bar = auto.EditControl(AutomationId='addressEditBox')
else:
win = auto.PaneControl(Depth=1, ClassName='Chrome_WidgetWin_1', SubName=browser)
temp = win.PaneControl(Depth=1, Name=browser).GetChildren()[1].GetChildren()[0]
for bar in temp.GetChildren():
last = bar.GetLastChildControl()
if last and last.Name != '':
break
addr_bar = bar.GroupControl(Depth=1, Name='').EditControl()
url = addr_bar.GetValuePattern().Value
return url
print(get_browser_tab_url('Edge'))
print(get_browser_tab_url('Google Chrome'))
print(get_browser_tab_url('Cent Browser'))
This should work:
import uiautomation as auto
control = auto.GetFocusedControl()
controlList = []
while control:
controlList.insert(0, control)
control = control.GetParentControl()
control = controlList[0 if len(controlList) == 1 else 1]
address_control = auto.FindControl(control, lambda c, d:
isinstance(c, auto.EditControl))
print('Current URL:')
print(address_control.GetValuePattern().Value)

Categories