• Intro to AutoHotkey HotStrings with AutoHotkey Intermediate AutoHotkey GUIs are Easy with AutoHotkey Intro to DOS & AutoHotkey

04: Automating Chrome to Set Text & Click a button

Automating Chrome with AutoHotkey

In the fourth session with GeekDude we look at out to Chrome and AutoHotkeyautomate setting text in a search field and then hitting the button to submit the search.

Automating Chrome to Set Text & Click a button


donate to GeekDudeIf you’re loving this, please consider donating to GeekDude!

AutoHotkey script for Automating Chrome to Set Text & Click a button


#Include   ;Remember to put Chrome in your library folder

#SingleInstance,Force
;**************************************
page:=Chrome.GetPageByTitle("AutoHotkey Community","contains") ;This will connect to the second index of a specific tab
If !IsObject(page){
MsgBox % "That wasn' t object / the page wasn't found"
ExitApp
}
page.Evaluate("document.querySelector('#keywords').value ='Chrome.ahk'")
Variable =document.querySelector('#keywords').value ='Chrome.ahk'
page.Evaluate(Variable)
var:="duh"
page.Evaluate("document.querySelector('#keywords').value ='" var "'")
page.Evaluate("document.querySelector('#search > fieldset > button').value ='Chrome.ahk'")

Notes for Automating Chrome to Set Text & Click a button

00:36     Go to AutoHotkey.com/boards/

00:44     Connect to tab using Chrome.GetPageByTitle(“AutoHotkey Community”) ;the default matchtype is “starts with”

01:23     Look at page structure using right-click and Inspect.  This opends Devtools with that element selected.

01:46     It has an ID of “keywords”, copy js path.  Which will give you queryselector(“#keywords”)

02:26     Use the .value to set some text in that box.

03:00     page.Evaluate(“document.querySelector(‘#keywords’).value =’Chrome.ahk'”)

04:01     Make sure inside the JavaScript you use the “=”, not “:=”

04:15     Some people don’t want to have to learn JavaScript.  When using Chrome, you’re going to have to learn JavaScript.

04:56     When using Chrome.ahk, we’re injecting JavaScript.  So best to learn

05:54     The button is right next to the input.  You can go back to the page and right-click the button, then hit Inspect

06:13     Test the new js path.  Instead of using .value, use .click

06:42     Test in Chrome developer tool

07:18     When running an Evaluate method, it waits for the previous Evaluate to finish (so no need to sleep between them).

07:44     If you run into a problem where you think it is happening too quickly, check the forum for some solutions

08:40     Sometimes what you want to input won’t always be a static string.  If you’re trying to reference a variable, you need to use the expression syntax.  In an expression, you’re not just assigning text, you’re doing math or making function calls.

Variable =document.querySelector(‘#keywords’).value =’Chrome.ahk’

page.Evaluate(Variable)

page.Evaluate(“document.querySelector(”#keywords ‘).value ='” variablevar:=”duh”

page.Evaluate(“document.querySelector(‘#keywords’).value ='” var “‘”) “‘”)

10:48     This works because AutoHotkey splits everything up on a given line.   First is a name of a function, then says this is inside the function, then this is text inside a function.  Then builds from left to right as to the string that will be used.

12:15     AutoHotkey proceeds left to right when evaluating an expression

12:40     when you use := you’re in expression assignment mode.

13:25     With just single = you’re in plain-text mode.  It reads it as text

15:00     When automating a site, you don’t know what kind of buffer’s they have to prevent scraping / botting.

15:49     When you start automating, you might start seeing Captcha’s everywhere

16:04     Sites get really good at looking like a normal site to a user, but looking like an impenetrable fortress to code

16:36     If your variable contains a single quote or other special charachters, JavaScript will interpret it as code instead of text.

17:13     JavaScript string escape sequence will replace characters with special escape sequences

Not mentioned in Video but GeekDude wrote me after

You can escape JavaScript code using Coco’s JSON library does actually do that escaping that we discussed when talking about putting data on the page. The syntax for invoking it looks like this:

variable = 123`r`n456’quote”quote

page.Evaluate(“document.querySelector(‘#whatever’).value = ” Chrome.Jxon_Dump(variable))

The dump function will automatically escape anything that needs escaped and add quotes to anything that needs quotes.

 

 

Cross browser web scraping with AutoHotkey and Selenium

AutoHotkey Merchandise-White Stress ball

While AutoHotkey is an amazing tool for Web Scraping, many people complain about being limited to connecting with COM to IE.   In the below videos I AutoHotkey and Seleniumwalk through how you can use AutoHotkey and Selenium to automate web scraping in virtually any browser you wish.  🙂

Update: 5/19/2020–  While to the best of my knowledge Selenium still works, when automating Chrome, I recommend using GeekDude’s Chrome class.  I have some examples of working with an older version of his Chrome class here.

Installing Selenium

In order to control Selenium with AutoHotkey you need to install the SeleniumBasic.  The current version is 2.09.0 and can be downloaded here.  Selenium is now on version 3 and there is a new SeleniumBasic version promised to be released soon which will connect to version 3 of Selenium.  Make sure you download the WebDrivers of choice for your browsers.

If all of this sounds confusing, don’t feel bad.  It is ridculous!  I found this post which documents/clarifies much of the confusion (although Selenium 3 is now out)

Please note several people reported when installing Selenium Basic it did not install in the program files location (i.e. here: C:\Program Files\SeleniumBasic or C:\Program Files (x86)\SeleniumBasic).  They also had problems getting Selenium to launch.   I recommend you make sure Selenium installs into one of the Program Files location and also make sure you get the Selenium drivers installed.  After install I had the following files on my computer:

  • C:\Program Files\SeleniumBasic\operadriver.exe
  • C:\Program Files\SeleniumBasic\chromedriver.exe
  • C:\Program Files\SeleniumBasic\edgedriver.exe
  • C:\Program Files\SeleniumBasic\iedriver.exe

After installing the Selenium Basic- Make sure you get the latest Chrome driver here and extract the “chromedriver.exe” into the folder where SeleniumBasic is installed. Also keeping your Chrome version up to date.  Currently I’m running 64.0.3282.39 64-bit version of Chrome and am using a 32-bit version of Selenium Webdriver (as there is no 64 bit version of Selenium webdriver).

Here are some links you might want to review (but you’ll need to adapt them for your purposes)

AutoHotkey Bottle 3

Using AutoHotkey and Selenium across various browsers

This video I show two ways I’ve learned how to start-up the Selenium Webdriver with AutoHotkey.

driver:= ComObjCreate("Selenium.WebDriver") ;Web driver
driver.Start("firefox","http://duckduckgo.com/") ;chrome, firefox, ie, phantomjs, edge
driver.Get("/")

driver:= ComObjCreate("Selenium.CHROMEDriver") ;Chrome driver
;~  driver:= ComObjCreate("Selenium.IEDriver") ;Chrome driver
;~  driver:= ComObjCreate("Selenium.FireFoxDriver") ;Chrome driver
driver.Get("http://duckduckgo.com/")

Tutorial showing how to start up and navigate with AutoHotkey and Selenium

 Squishy Ball 2

Getting information from a page with Selenium and AutoHotkey

While there are a lot of similarities to data extraction in Selenium, there are quite a few differences as well. The below code is what I use in the following video.  It demonstrates some ways that you can extract data from a web page via Selenium and AutoHotkey.

driver:= ComObjCreate("Selenium.CHROMEDriver") ;Chrome driver
driver.Get("https://the-automator.com/")

;!!!!DO NOT USE!!!  driver.findElement(By.id("search_form_input_homepage")).SendKeys("hello") ; Java bindings of Selenium. !!!!DO NOT USE!!!

MsgBox % driver.findElementByID("site-description").Attribute("innerText") ;note case sensitive
MsgBox % driver.executeScript("return document.getElementById('site-description').innerText")
MsgBox % driver.executeScript("return document.getElementById('site-description').outerHTML")

MsgBox % driver.findElementByID("cat").Attribute("value") ;lowercase value
MsgBox % driver.findElementsByName("cat").item[1].Attribute("outerHTML")
MsgBox % driver.findElementsByName("cat").item[1].Attribute("textContent")
MsgBox % driver.findElementsByName("cat").item[1].Attribute("innerText")
MsgBox % driver.findElementsByName("cat").item[1].Attribute("option value")
MsgBox % driver.findElementByName("s").Attribute("innerTEXT")

 

Setting information on a pageAutoHotkey Bottle 1

Selenium and AutoHotkey are pretty different in how you set information.  Selenium has a “sendkeys” method which seems to be pretty reliable at triggering events on a page.

  • Make sure you review this:  Send keys to value:  ;Note: you need to add “driver” e.g. .SendKeys(driver.Keys.ENTER)
driver:= ComObjCreate("Selenium.CHROMEDriver") ;Chrome driver
driver.Get("https://the-automator.com/")

;~  !!!!DO NOT USE!!!  driver.findElement(By.id("search_form_input_homepage")).SendKeys("hello") ; Java bindings of Selenium. !!!!DO NOT USE!!!

driver.findElementsByName("s").item[2].SendKeys("hello world")
driver.findElementsByName("s").item[2].SendKeys(driver.Keys.ENTER) ;http://seleniumhome.blogspot.com/2013/07/how-to-press-keyboard-in-selenium.html
MsgBox pause
driver.executeScript("arguments[0].setAttribute('value', 'hello world')", driver.findElementsByName("s")) ;sets value
driver.findElementsByName("cat").item[2].SendKeys("hello world")

driver.findElementsByName("cat").item[1].click() ;1 based, not zero

Setting text & clicking items on a page with Selenium and AutoHotkey

 

AutoHotkey Merchandise-White Stress ballUsing your Chrome Profile (Avoiding the need to re-login to a site)

In this video I demonstrate how you can leverage your Chrome profile so you do not need to keep logging into a website with Chrome

driver:= ComObjCreate("Selenium.CHROMEDriver") ;Chrome driver
; put this "chrome://version/"  in the url in chrome to find path to profile
 ;https://stackoverflow.com/questions/25779027/load-default-chrome-profile-with-webdriverjs-selenium
driver.SetProfile("H:\Temp\Chrome\Cache\cache\Default") ; 'Full path of the profile directory
url:="https://www.linkedin.com/feed/?trk="
driver.Get(url)

 

 AutoHotkey Bottle 4

Iterating over Objects with Selenium and AutoHotkey

In the below video I demonstrate some of the important differences when iterating over objects with Selenium and AutoHotkey.    A COM based object does not have an enumerator thus you cannot simply use a for-loop to iterate over them.   Selenium does does have an enumerator however the objects are held in the Keys (not the values).

pwb := WBGet()
obj:=pwb.document.GetElementsByName("s") ;.length
for k, v in obj
    MsgBox % v.outerHTML

loop, % obj.length
    COM_Data.= a_index a_tab obj[a_index-1].outerhtml "`n" ;zero based

SciTE_Output(COM_Data) ;Text,Clear=1,LineBreak=1,Exit=0  ;https://the-automator.com/scite-output-pane/
MsgBox pause

^t::
driver:= ComObjCreate("Selenium.IEDriver") ;Chrome driver
driver.Get("https://the-automator.com/")

;~  MsgBox % driver.FindElementsByName("s").Length ; does not work
MsgBox % driver.FindElementsByName("s").Count ;need to use count


obj:=driver.FindElementsByName("s")
for k,v in obj {
  ;~  MsgBox % IsObject(v) a_tab v
     Selenium_Data.= a_index a_tab k a_tab   k.Attribute("outerHTML") "`n"
}
SciTE_Output(Selenium_Data,1) ;Text,Clear=1,LineBreak=1,Exit=0

 

Demo video showing how to iterate over objects in Selenium

 AutoHotkey Bottle 3

Various Selenium methods for getting & setting data on a page

In this tutorial I walk through various ways to get/set data on a page. With Selenium you can use both CSS and Xpath which are like QuerySelector.

I also shared these two resources from Michael Sorens which present the same data

driver:= ComObjCreate("Selenium.CHROMEDriver") ;Chrome driver
driver.Get("https://the-automator.com/")

MsgBox,,ByTag name-Just first,% driver.findElementByTag("P").Attribute("outerHTML") ;ByTag (name)-(just first)
MsgBox,,ByTag name-First in Array,% driver.findElementsByTag("P").item[1].Attribute("outerHTML") ;ByTag (name)-Array
MsgBox,,ByID      ,% driver.findElementByID("site-description").Attribute("outerHTML") ;ByID
MsgBox,,ByName-Just First   ,% driver.findElementByName("s").Attribute("outerHTML") ;ByName (Just first)
MsgBox,,ByName (array),% driver.findElementsByName("s").item[2].Attribute("outerHTML") ;ByName- array- 2nd
MsgBox,,ByClass-First,% driver.findElementByClass("entry-title").Attribute("outerHTML") ;ByClass - (Just first)
MsgBox,,ByClass-Array,% driver.findElementsByClass("entry-title").item[2].Attribute("outerHTML") ;ByClass - Array
MsgBox,,Partial Match on Link text,% driver.findElementByPartialLinkText("a time").Attribute("outerHTML") ;partial match text
MsgBox,,Full Match on Link text,% driver.findElementByLinkText("Automating my world; 1 script @ a time!").Attribute("innerText") ;Full match of link text

;***********css*******************
MsgBox,,CSS-Tag &Input,% driver.findElementsByCss("input[name='s']").item[1].Attribute("outerHTML") ;ByCss: tag of Input and name of S
MsgBox,,CSS-Just anme,% driver.findElementsByCss("[name='s']").item[1].Attribute("outerHTML") ;ByCss: Just use name
MsgBox,,CSS-JustID,% obj:=driver.findElementsByCss("[id='site-description']").item[1].Attribute("outerHTML") ;ByCss: just by id
MsgBox,,CSS-Class,% obj:=driver.findElementsByCss("[class='entry-title']").item[1].Attribute("outerHTML") ;ByCss: Class
MsgBox,,CSS-Atag element and url,% obj:=driver.findElementsByCss("a[href='https://www.linkedin.com/in/joeglines']").item[1].Attribute("outerHTML") ;ByCss: A tag & href=URL

;***********xPath***https://addons.mozilla.org/en-us/firefox/addon/firepath/****************
MsgBox,,XPATH-ID & Tag,% driver.findelementbyxpath(".//*[@id='site-title']/span/a").Attribute("outerHTML") ;XPath: ID=site-title & span tag
MsgBox,,XPATH-ID and Input Hierarchy,% driver.findelementbyxpath(".//*[@id='prime_nav']/li[8]/form/label/input").Attribute("outerHTML") ;XPath: ID=prime_Nave & tag heirarchy

 

Various methods from Selenium & by using JavaScript Execution

I went through and documented some of the additinol methods I used from Selenium & by injecting JavaScript. Check them out below as well as the video walking through the usage.

driver:= ComObjCreate("Selenium.CHROMEDriver") ;Chrome driver
;~  driver.SetProfile("H:\Temp\Chrome\Cache\cache\Default") ; 'Full path of the profile directory
driver.Get("https://the-automator.com/")


MsgBox,,Title via JavaScript, % driver.executeScript("return document.title") ;gets title
MsgBox,,Title, % Driver.Title ;Displays gets tab title
MsgBox pause
driver.executeScript("window.location = 'https://www.youtube.com/user/JoeGlines'") ;navigate using javascript
MsgBox % driver.executeScript("return document.location.pathname") ;get path of url
MsgBox pause
MsgBox,,Title, % Driver.Title ;Displays gets tab title
driver.executeScript("history.go(-1)") ;Go back one page
MsgBox pause
MsgBox,,Title, % Driver.Title ;Displays gets tab title
driver.executeScript("history.go(0)") ;refresh page
MsgBox pause
driver.executeScript("history.go(1)") ;Go forward one page
driver.executeScript("window.scrollBy(0,550)") ;scroll down page
MsgBox pause
driver.executeScript("window.scrollBy(0,950)") ;scroll down page
MsgBox % driver.executeScript("return document.domain") ;get domain of current page

MsgBox,,URL, % driver.url() ;gets current URL
MsgBox,,Href, % driver.executeScript("return document.location.href") ;get full url
MsgBox,,Protocol, % driver.executeScript("return document.location.protocol") ;get protocol
driver.Get("https://the-automator.com/?s=Selenium")
MsgBox,,Search, % driver.executeScript("return document.location.search") ;get everything from ? on

driver.executeScript("window.open('https://www.youtube.com/user/JoeGlines','_target','resizable=yes')") ;open new tab with new destiation
MsgBox pause
driver.executeScript("window.open('','_blank','resizable=yes')") ;open new blank tab
return

AutoHotkey Bottle 4Maneuvering Frames in Selenium with AutoHotkey

The below code provides some insights on how to navigate frames with AutoHotkey

driver:= ComObjCreate("Selenium.CHROMEDriver") ;Chrome driver
  driver.Get("http://the-internet.herokuapp.com/nested_frames")
  ;switch to a child frame
  MsgBox % "count before change = " driver.FindElementsByTag("frame").count
  driver.SwitchToFrame("frame-top")
  MsgBox % "count after change = " driver.FindElementsByTag("frame").count
  driver.SwitchToFrame("frame-middle")
MsgBox % driver.FindElementById("content").Text
return

Downloading files with Selenium and AutoHotkey

In this tutorial I demonstrate how I used AutoHotkey and Selenium to download a PDF file. The same process will work for other files that are not, automatically, opened by Chrome.

driver:= ComObjCreate("Selenium.CHROMEDriver") ;Chrome driver
;~  driver.SetProfile("H:\Temp\Chrome\Cache\cache\Default") ; 'Full path of the profile directory
driver.SetPreference("download.default_directory","c:\temp") ;set path to where you want the file saved
driver.get("chrome://settings-frame/content")
driver.findElementByID("pdf-section").click() ;disable open pdf
driver.Get("https://the-automator.com/download/group-tool.pdf")

Connecting to a current instance of ChromeAutoHotkey Merchandise-White Stress ball

Thankfully tmplinshi has come up with a solution on how to connect to an already launched version of Chrome.  Granted, you’ll need to launch Chrome with some command line parameters but this is an easy tweak to do by just adding them to your main shortcut to Chrome you’ll be able to connect to a current running Chrome window!

Here’s what you need to do for prep-work:

  1. Make sure all current versions of Chrome are closed
  2. Create a shortcut to chrome with this path: chrome.exe –remote-debugging-port=9222
  3. Launch Chrome from your new shortcut

Then you can use the below code to connect with it!  Check out the below video demonstrating how it works.

;********************Connect to Chrome and show title***********************************
driver := ChromeGet()
MsgBox, % driver.Window.Title "`n" driver.Url
return

ChromeGet(IP_Port := "127.0.0.1:9222") {
	driver := ComObjCreate("Selenium.ChromeDriver")
	driver.SetCapability("debuggerAddress", IP_Port)
	driver.Start()
	return driver
}

;********************Create new Chrome window***********************************
^t::
driver:= ComObjCreate("Selenium.CHROMEDriver") ;Chrome driver
driver.Get("https://the-automator.com/")
MsgBox, % driver.Window.Title "`n" driver.Url
return

;********************Launch Chrome with parameters***********************************
^+r::run chrome.exe "--remote-debugging-port=9222" ;Run in debugging mode

 

  • Intro to AutoHotkey HotStrings with AutoHotkey Intermediate AutoHotkey GUIs are Easy with AutoHotkey Intro to DOS & AutoHotkey