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

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.

Related

Stopping a function based on a value

I am running a python script on a raspberry-pi.
Essentially, I would like a camera to take a picture every 5 seconds, but only if I have set a boolean to true, which gets toggled on a physical button.
initially I set it to true, and then in my while(true) loop, I want to check to see if the variable is set to true, and if so, start taking pictures every 5 seconds. The issue is if I use something like time time.sleep(5), it essentially freezes everything, including the check. Combine that with the fact that I am using debouncing for the button, it then becomes impossible for me to actually toggle the script since I would have to press it exactly after the 5s wait time, right for the value check... I've been searching around and I think the likely solution would have to include threading, but I can't wrap my head around it. One kind of workaround I thought of would be to look at the system time and if the seconds is a multiple of 5, then take picture (all within the main loop). This seems a bit sketchy.
Script below:
### Imports
from goprocam import GoProCamera, constants
import board
import digitalio
from adafruit_debouncer import Debouncer
import os
import shutil
import time
### GoPro settings
goproCamera = GoProCamera.GoPro()
### Button settings
pin = digitalio.DigitalInOut(board.D12)
pin.direction = digitalio.Direction.INPUT
pin.pull = digitalio.Pull.UP
switch = Debouncer(pin, interval=0.1)
save = False #this is the variable
while(True):
switch.update()
if switch.fell:
print("Pressed, toggling value")
save = not save
if save:
goproCamera.take_photo()
goproCamera.downloadLastMedia()
time.sleep(5)
Here's something to try:
while(True):
switch.update()
if switch.fell:
print("Pressed, toggling value")
save = not save
if save:
current_time = time.time()
if current_time - last_pic_time >= 5:
goproCamera.take_photo()
goproCamera.downloadLastMedia()
last_pic_time = current_time
Depending on exactly what sort of behavior you want, you may have to fiddle with when and how often time.time() is called.
Cheers!
Maybe something like this?
import threading
def set_interval(func, sec):
def func_wrapper():
set_interval(func, sec)
func()
t = threading.Timer(sec, func_wrapper)
t.start()
return t
We call the function above inside the main loop.
Wrap your while loop content on a function:
def take_photo:
goproCamera.take_photo()
goproCamera.downloadLastMedia()
Now we create a flag initially set to False to avoid creating multiple threads.
Notice that I did this before the while loop. We just need a starting value here.
active = False
while(True):
switch.update()
if switch.fell:
print("Pressed, toggling value")
save = not save
if save: # we need to start taking photos.
if not active: # it is not active... so it is the first time it is being called or it has been toggled to save as True again.
photo_thread = set_interval(take_photo, 5) # grabbing a handle to the thread - photo_thread - so we can cancel it later when save is set to False.
active = True # marking as active to be skipped from the loop until save is False
else:
try: # photo_thread may not exist yet so I wrapped it inside a try statement here.
photo_thread.cancel() # if we have a thread we kill it
active = False #setting to False so the next time the button is pressed we can create a new one.
Let me know if it works. =)
What I ended up doing:
### Imports
from goprocam import GoProCamera, constants
import board
import digitalio
from adafruit_debouncer import Debouncer
import os
import time
import threading
### GoPro settings
gopro = GoProCamera.GoPro()
### Button settings
pin = digitalio.DigitalInOut(board.D12)
pin.direction = digitalio.Direction.INPUT
pin.pull = digitalio.Pull.UP
switch = Debouncer(pin, interval=0.1)
### Picture save location
dir_path = os.path.dirname(os.path.realpath(__file__))
new_path = dir_path+"/pictures/"
save = False
### Functions
def takePhoto(e):
while e.isSet():
gopro.take_photo()
gopro.downloadLastMedia()
fname = '100GOPRO-' + gopro.getMedia().split("/")[-1]
current_file = dir_path+'/'+fname
if os.path.isfile(current_file):
os.replace(current_file, new_path+fname) #move file, would be cleaner to download the file directly to the right folder, but the API doesn't work the way I thought it did
e.wait(5)
### Initial settings
e = threading.Event()
t1 = threading.Thread(target=takePhoto, args=([e]))
print("Starting script")
while(True):
switch.update()
if switch.fell:
#toggle value
save = not save
if save:
e.set() #should be taking pictures
else:
e.clear() #not taking pictures
if not t1.is_alive(): #start the thread if it hasn't been yet
if e.is_set():
t1.start()

How To Delete A Row In Excel Sheet Using Python?

I am working on a Selenium program using Python where I want to delete a row in the Excel sheet using Openpyxl library. The issue is I don't know how to implement the delete function in my program. Below here have 2 classes, AutoTest.py which is the testing class and NewCard.py which is the class where I implemented POM(Page Object Model). May I know how to implement the function to delete just 1 row in accordance with my program?
AutoTest.py
import unittest
import HtmlTestRunner
from selenium import webdriver
import openpyxl
import sys
sys.path.append("C:\Users\lukegoh\Desktop\Python Projects\SoftwareAutomationTesting")
from pageObjects.LoginPage import LoginPage
from pageObjects.HomePage import Homepage
from pageObjects.NewCard import NewCard
excpath = r"C:\Users\lukegoh\Desktop\Python Projects\SoftwareAutomationTesting\excel\new\ABT0475EC Card Init Detailed Rpt Test 01 - v13_1.xlsx"
excsheetName = "ABT0475EC Card Initialization D"
class AutoTest(unittest.TestCase):
baseURL = "https://10.2.5.215:33000/viewTopUpRequest"
username = "ezltest2svc"
password = "Password123!"
driver = webdriver.Chrome()
#classmethod
def setUpClass(cls):
cls.driver.get(cls.baseURL)
cls.driver.maximize_window()
cls.driver.implicitly_wait(10)
def test_1(self): #This is scenario 1- to create request for new card
lp = LoginPage(self.driver)
hp = Homepage(self.driver)
np = NewCard(self.driver)
lp.setUsername(self.username)
lp.setPassword(self.password)
lp.clickLogin()
hp.clickutil()
hp.clickreqNewCard()
np.setJobOrder()
np.clickExcel()
np.setTopUpAmount()
np.calculateAmount()
if not np.clickSubmit():
np.deleteRow(excpath,excsheetName,3)
else:
print("Test Passed")
# #classmethod
# def tearDownClass(cls):
# cls.driver.close()
# print("Test Completed")
#if __name__ == '__main__':
# unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(output='C:/Users/lukegoh/Desktop/Python Projects/SoftwareAutomationTesting/reports'))
NewCard.py
import openpyxl
class NewCard:
jobOrder_xpath="//body/div[#id='wrapper']/div[3]/div[1]/div[1]/div[1]/div[1]/input[1]"
excelButton_xpath="//input[#id='img']"
topup_textbox_xpath="//input[#id='input-live']"
calculateAmount_xpath="(//button[#type='button'])[4]"
buttonSubmit_xpath="(//button[#type='button'])[5]"
def __init__(self,driver):
self.driver=driver
def setJobOrder(self):
self.driver.find_element_by_xpath(self.jobOrder_xpath).send_keys("AutoTest1")
def clickExcel(self):
self.driver.find_element_by_xpath(self.excelButton_xpath).send_keys(r"C:\Users\lukegoh\Desktop\Python Projects\SoftwareAutomationTesting\excel\new\ABT0475EC Card Init Detailed Rpt Test 01 - v13_1.xlsx")
def setTopUpAmount(self):
self.driver.find_element_by_xpath(self.topup_textbox_xpath).send_keys("10")
def calculateAmount(self):
self.driver.find_element_by_xpath(self.calculateAmount_xpath).click()
def clickSubmit(self):
self.driver.find_element_by_xpath(self.buttonSubmit_xpath).click()
def deleteRow(file, sheetName, rownum):
workbook = openpyxl.load_workbook(file)
sheet = workbook.get_sheet_by_name(sheetName)
sheet.cell(row=rownum).
workbook.save(file)
If you check OpenPyXL docs, it has something called delete_rows()
Syntax delete_rows(idx, amount=1), it deletes from idx and goes on deleting for amount
import openpyxl
filename = "example.xlsx"
wb = openpyxl.load_workbook(filename)
sheet = wb['Sheet1']
sheet.delete_rows(row_number, 1)
wb.save(filename)
Docs for delete_rows(): https://openpyxl.readthedocs.io/en/stable/api/openpyxl.worksheet.worksheet.html#openpyxl.worksheet.worksheet.Worksheet.delete_rows
use pandas
import pandas as pd
df = pd.read_excel("test.xlsx")
df = df.drop(df.index[1])
df.to_excel('test1.xlsx')

How to update table of contents in docx-file with python on linux?

I've got a problem with updating table of contents in docx-file, generated by python-docx on Linux. Generally, it is not difficult to create TOC (Thanks for this answer https://stackoverflow.com/a/48622274/9472173 and this thread https://github.com/python-openxml/python-docx/issues/36)
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
paragraph = self.document.add_paragraph()
run = paragraph.add_run()
fldChar = OxmlElement('w:fldChar') # creates a new element
fldChar.set(qn('w:fldCharType'), 'begin') # sets attribute on element
instrText = OxmlElement('w:instrText')
instrText.set(qn('xml:space'), 'preserve') # sets attribute on element
instrText.text = 'TOC \o "1-3" \h \z \u' # change 1-3 depending on heading levels you need
fldChar2 = OxmlElement('w:fldChar')
fldChar2.set(qn('w:fldCharType'), 'separate')
fldChar3 = OxmlElement('w:t')
fldChar3.text = "Right-click to update field."
fldChar2.append(fldChar3)
fldChar4 = OxmlElement('w:fldChar')
fldChar4.set(qn('w:fldCharType'), 'end')
r_element = run._r
r_element.append(fldChar)
r_element.append(instrText)
r_element.append(fldChar2)
r_element.append(fldChar4)
p_element = paragraph._p
But later to make TOC visible it requires to update fields. Mentioned bellow solution involves update it manually (right-click on TOC hint and choose 'update fields'). For the automatic updating, I've found the following solution with word application simulation (thanks to this answer https://stackoverflow.com/a/34818909/9472173)
import win32com.client
import inspect, os
def update_toc(docx_file):
word = win32com.client.DispatchEx("Word.Application")
doc = word.Documents.Open(docx_file)
doc.TablesOfContents(1).Update()
doc.Close(SaveChanges=True)
word.Quit()
def main():
script_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
file_name = 'doc_with_toc.docx'
file_path = os.path.join(script_dir, file_name)
update_toc(file_path)
if __name__ == "__main__":
main()
It pretty works on Windows, but obviously not on Linux. Have someone any ideas about how to provide the same functionality on Linux. The only one suggestion I have is to use local URLs (anchors) to every heading, but I am not sure is it possible with python-docx, also I'm not very strong with these openxml features. I will very appreciate any help.
I found a solution from this Github Issue. It work on ubuntu.
def set_updatefields_true(docx_path):
namespace = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
doc = Document(docx_path)
# add child to doc.settings element
element_updatefields = lxml.etree.SubElement(
doc.settings.element, f"{namespace}updateFields"
)
element_updatefields.set(f"{namespace}val", "true")
doc.save(docx_path)## Heading ##
import docx.oxml.ns as ns
def update_table_of_contents(doc):
# Find the settings element in the document
settings_element = doc.settings.element
# Create an "updateFields" element and set its "val" attribute to "true"
update_fields_element = docx.oxml.shared.OxmlElement('w:updateFields')
update_fields_element.set(ns.qn('w:val'), 'true')
# Add the "updateFields" element to the settings element
settings_element.append(update_fields_element)

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