.exe compiled for python driver here:
https://github.com/samfisherirl/Selenium_Py.ahk (if you enjoy, drop a star for an up and coming dev)
Finding web elements https://www.selenium.dev/documentation/webdriver/elements/finders/
Locating the elements based on the provided locator values. https://www.selenium.dev/documentation/webdriver/elements/interactions/
Interacting with web elementshttps://www.selenium.dev/documentation/webdriver/elements/interactions/
todo: needs to be able to input form data, should be running soon.
A high-level instruction set for manipulating chrome and web controls.
settings := [A_ScriptDir . "\lib\selenium_ahk.exe"]
chrome := Selenium.Commands(["get", "https://slatestarcodex.com/"], settings)
PID := chrome.PID ; manipulate window
chrome.start()
; initiate driver, if first time, downloads appropriate webdriver automatically & restarts
; navigates to initial url request
chrome.newCall(["click", "PARTIAL_LINK_TEXT", "CODEX"])
chrome.newCall(["get_link", "ID", "a"])
chrome.newCall(["click", "CLASS_NAME", "data"])
adding this week:
chrome.newCall(["store_element", "ID", "a"])
chrome.newCall(["send_input", "these keys are being sent to input box"])
MsgBox(chrome.read())
;upon retrieving value like "all_links" or "get_link", log is stored locally and object has retrievable value
chrome.newCall(["all_links"])
MsgBox(chrome.read())
chrome.quit()
Code for AHK:
Code: Select all
settings := [A_ScriptDir . "\lib\selenium_ahk.exe"]
chrome := Selenium.Commands(["get", "https://slatestarcodex.com/"], settings)
chrome.start() ; true if no value but successful
PID := chrome.PID ; manipulate window
chrome.newCall(["click", "PARTIAL_LINK_TEXT", "CODEX"])
chrome.newCall(["get_link", "PARTIAL_LINK_TEXT", "ARCHIVE"])
MsgBox(chrome.read())
chrome.newCall(["all_links"])
chrome.newCall(["get_link", "CLASS_NAME", "data"])
MsgBox(chrome.read())
; returns link by text name
chrome.quit()
/*
chrome.newCall(["click", "TAG_NAME", "A"])
chrome.newCall(["click", "TAG_NAME", "A"])
find_element(By.ID, "id")
find_element(By.NAME, "name")
find_element(By.XPATH, "xpath")
find_element(By.LINK_TEXT, "link text")
find_element(By.PARTIAL_LINK_TEXT, "partial link text")
find_element(By.TAG_NAME, "tag name")
find_element(By.CLASS_NAME, "class name")
find_element(By.CSS_SELECTOR, "css selector")
*/
class Selenium
{
class Commands
{
__New(command, settings) {
key := command.Length
this.function := command[1]
this.key := command.Length
this.PID := ""
SplitPath(settings[1], , &folder)
this.folder := folder
this.temp := folder . "\temp.txt"
this.log := folder . "\log.txt"
this.out := folder . "\log_out.txt"
this.selpath := Settings[1]
this.storage := ""
if (key > 1) {
this.paramX := command[2]
if (key > 2) {
this.paramY := command[3]
if (key > 3) {
this.paramZ := command[4]
} }
}
this.command := command
}
start() {
if !FileExist(this.log) and !FileExist(this.temp) {
msg := "This may be your first time using, please restart after selenium driver download."
this.stringify()
Run(this.selpath, this.folder, , &PID)
exitapp
}
this.clean(this.log)
this.clean(this.temp)
this.stringify()
Run(this.selpath, this.folder, , &PID)
this.pid := PID
this.call()
sleep(1000)
}
call() {
this.clean(this.log)
this.clean(this.out)
this.stringify()
this.loopEngage()
Selenium.Commands.delLog(this.out)
}
loopEngage(){
f := this.function
if (instr(f,"get_link")) or (instr(f,"get_links")) or (instr(f,"all_links")) {
this.readLog(this.out, 2)
}
else if (instr(f,"quit")) {
exitapp
}
else {
this.readLog(this.log, 1)
}
}
stringify(){
stringify := ""
loop this.command.Length {
stringify .= "--" . this.command[A_Index]
}
Selenium.Commands.delLog(this.temp)
sleep(5)
FileAppend(stringify, this.temp)
}
quit(){
this.newCall(["quit"])
exitapp
}
clean(file){
if FileExist(file) {
Selenium.Commands.delLog(file)
}
}
newCall(params) {
Sleep(500)
this.command := params
this.key := params.Length
this.function := params[1]
if (this.key > 1) {
this.paramX := params[2]
if (params.Length > 2) {
this.paramY := params[3]
if (params.Length > 3) {
this.paramZ := params[4]
}
}
}
this.call()
}
readLog(file, mode) {
x := "`n"
loop 50
{
if (A_Index == 50) {
msg := this.function . x .
file . x .
this.PID . x .
x . this.storage . x . mode
FileAppend(msg, A_ScriptDir "\er.txt")
Msgbox("Looping, not receiving updates from selenium`nLogdump:`n" . msg)
processclose(this.PID)
exitapp
}
else if FileExist(file) {
try {
output := FileRead(file)
}
catch {
Sleep(200)
continue
}
if (mode == 1) {
if (instr(output, "False")) {
break
}
else {
Sleep(200)
continue
}
}
else if (mode == 2) {
this.storage := output
Selenium.Commands.delLog(file)
break
}
else {
if (output == this.paramX) {
sleep(200)
break
}
else {
sleep(200)
continue
}
}
}
else {
Sleep(200)
continue
}
}
}
read()
{
return this.storage
}
static delLog(log) {
loop 10 {
try {
FileDelete(log)
}
catch {
sleep(50)
}
}
}
}
}
Python script that handles webdriver download and interaction. Go to github to get compiled version:
Code: Select all
from selenium.webdriver import Chrome #, ChromeOptions
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from time import sleep
from pathlib import Path
log = Path.cwd() / "log.txt"
temp = Path.cwd() / "temp.txt"
out = Path.cwd() / "log_out.txt"
#options = ChromeOptions()
#options.add_experimental_option('excludeSwitches', ['enable-logging'])
class Sel:
def __init__(self):
self.links = []
self.running = True
self.element = None
self.lastcommand = ""
self.counter = 0
def listener(self):
while True:
sleep(1)
if self.running == False:
break
else:
self.reader()
def reader(self):
if Path.is_file(temp):
with open(temp, "r") as f:
command = f.read()
with open(log, "w") as f:
f.write("True")
if command == self.lastcommand or command == "":
return True
else:
print(f"\n\nSuccess!\n{command}\n")
self.lastcommand = command
self.commander(command)
else:
Sel.write_ahk_log("False", log)
@staticmethod
def write_ahk_log(notes, file):
with open(file, "w") as f:
print(notes)
f.write(notes)
def commander(self, command):
try:
counter = command.count("--")
if counter == 2:
command = command.split("--")
if command[1] == "quit":
self.close_driver()
else:
self.call_function_by_name(command[1], command[2])
elif counter == 3:
command = command.split("--")
self.call_function_by_name(command[1], command[2], command[3])
elif counter == 1:
command = command.split("--")
if command[1] == "quit":
self.close_driver()
else:
self.call_function_by_name(command[1])
except Exception as e:
print(str(e))
Sel.write_ahk_log(str(e), out)
self.close_driver()
def call_function_by_name(self, function_name, *arg):
print(f"\n\ncall\n{function_name}\n{arg}\n")
func = getattr(self, function_name)
if not arg:
func()
elif len(arg) == 1:
print(str(arg))
func(arg[0])
elif len(arg) == 2:
print(str(arg))
func(arg[0], arg[1])
Sel.write_ahk_log("False", log)
def get(self, url):
"""Navigates to the specified URL"""
driver.get(url)
return True
def find_element(self, locator, value):
return driver.find_element(locator, value)
def find_elements(self, locator, value):
return driver.find_elements(locator, value)
def by(self, locator, value):
com = getattr(By, locator)
self.element = self.find_element(com, value)
def click(self, locator, value):
com = getattr(By, locator)
self.find_element(com, value).click()
#print("\n\n\nclicking")
#com = getattr(By, locator)
#link = self.find_element(com, value).get_attribute("href")
#link.click()
def get_link(self, locator, value):
com = getattr(By, locator)
link = self.find_element(com, value)
out_data = link.get_attribute("href")
if "Message: no such element" in out_data:
self.err(self, out_data)
else:
self.write_listor_string(out_data)
return out_data
def all_links(self):
links = self.find_elements(By.TAG_NAME, "a")
urls = [link.get_attribute("href") for link in links]
text = [link.text for link in links]
list = {f"{k}: {v}" for k, v in zip(urls, text)}
self.write_listor_string(list)
# def all_links(self):
# links = driver.find_elements(By.TAG_NAME, "a")
# urls = [link.get_attribute("href") for link in links]
# text = [link.text for link in links]
# dic = {k: v for k, v in zip(urls, text)}
# self.write_listor_string(str(dic))
def wait_until_element_visible(self, locator, value, timeout=1):
WebDriverWait(driver, timeout).until(EC.visibility_of_element_located((locator, value)))
def pass_return_to_ahk(val):
pass
@staticmethod
def delete_er():
with open("er.txt", "w") as f:
f.write("")
def err(self, e):
print(str(e))
with open("er.txt", "a", errors="ignore") as f:
f.write(str(e))
with open("er.txt", "a", errors="ignore") as f:
f.write(str(e))
self.close_driver()
def write_listor_string(self, *args):
with open(out, "w", errors="replace") as f:
if args:
[f.write(f"{i}\n") for i in args]
Sel.write_ahk_log("False", log)
#################################################
def writer(self, dic, filename):
file = Path(__file__).parent / "log_out.txt"
with open(f"{file}", "w", errors="ignore") as f:
for k, v in dic.items():
f.write(f",{k},{v},\n")
Sel.write_ahk_log("False", log)
def close_driver(self):
"""Closes the webdriver instance"""
driver.quit()
self.running = False
return
if __name__ == "__main__":
log = Path.cwd() / "log.txt"
temp = Path.cwd() / "temp.txt"
out = Path.cwd() / "log_out.txt"
print(log)
print(out)
driver = Chrome(service=ChromeService(ChromeDriverManager().install()))
Sel.delete_er()
S = Sel()
S.get("https://www.slatestarcodex.com/")
S.all_links()
S.listener()
#drivers = Sel()
#drivers.get("https://www.github.com/")
#drivers.all_links()