Use AppleScript in a Safari Search

I have been trying to set up a search in Safari using script commands I found in UI Browser.

There are three lines in the code below.

  1. To set a value in the search block
    2.To return the value just set
  2. Select the text that was supposed to have been set in line 1.

This is the code.


activate application "Safari"
tell application "System Events"
	tell process "Safari"
		set value of UI element 1 of group 4 of toolbar 1 of window 1 to "yahoo"
		get value of UI element 1 of group 4 of toolbar 1 of window 1
		select UI element 1 of group 4 of toolbar 1 of window 1
	end tell
end tel
l

and this is the result

tell application “Safari”
activate
end tell
tell application “System Events”
set value of UI element 1 of group 4 of toolbar 1 of window 1 of process “Safari” to “yahoo”
get value of UI element 1 of group 4 of toolbar 1 of window 1 of process “Safari”
→ missing value
select UI element 1 of group 4 of toolbar 1 of window 1 of process “Safari”
→ UI element 1 of group 4 of toolbar 1 of window “Untitled spreadsheet - Google Sheets” of application process “Safari”
end tell
Result:
UI element 1 of group 4 of toolbar 1 of window “Untitled spreadsheet - Google Sheets” of application process “Safari” of application “System Events”

It processes all the commands but returns “missing value” after line 1 & 2 and then returns the value in the box without making any changes from line 3. The last line proves I think that I am in the correct box.

Any suggestions greatly appreciated

Thanks

Peter

Hi.

What’s in your Safari toolbar depends on your own settings, so the groups in your ‘toolbar 1’ may not be the same as on other people’s machines.

If by “search block” you mean what’s described in Safari’s toolbar customisation dialog as “Address and Search”, that particular UI element in Safari 11.1.1 contains one or more UI elements of its own. And what these sub-elements are varies according whether or not the field’s selected and whether or not the clickable graphics at either end of it are being shown. Sometimes there’s a ‘static text’ whose value is the text displayed in the field. Sometimes there’s a ‘text field’ instead with a similar value. If it’s a ‘text field’, the value can be changed. If it’s a ‘static text’, it can’t.

The only reliable way I can find to force the issue is to fake a Command-L keystroke to select the field. From there, you can either set the value of the ‘text field’ or simply ‘keystroke’ it:


activate application "Safari"
tell application "System Events"
	tell process "Safari"
		set frontmost to true
		keystroke "l" using command down
		--keystroke "yahoo"
		set value of text field 1 of UI element 1 of group 4 of toolbar 1 of window 1 to "yahoo"
	end tell
end tell

Hi Nigel

Thanks for your advice, I think I was making the job to hard and it is simpler as I always (in this instance) want to go to the same place to open to that page. As you will have noticed the Web Page is Yahoo finance. Then I want to enter the name of the stock I am interested into the search field on the Yahoo Finance page. The script below opens the page and although the cursor winds up in the correct box it does not enter the required stock symbol. In fact I think the open command puts the cursor there anyway .

As you can see I tried your suggestion of faking the Command L after I thought I had selected the field I wanted to insert the Stock symbol but that took me to the command bar in Safari. therefore my select command does not work.

As I mentioned I obtained the sequence to the filed using UI Browser.

Any further suggestions greatly appreciated, but in any event thanks for your help so far.

Peter

set SYM to text returned of (display dialog "Enter Symbol for Stock " default answer "")
display dialog SYM
activate application "Safari"
tell application "Safari"
	open location "www.finance.yahoo.com"
	delay 5 --to allow the page to load		
	tell application "System Events"
		tell process "Safari"
			
			select group 1 of text field 1 of group 1 of group 2 of UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window 1
			--keystroke "l" using command down
			set value of group 1 of text field 1 of group 1 of group 2 of UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window 1 to SYM
		end tell
	end tell
end tell

Here “tab group 1” doesn’t compile.

I used the brave old Accessibility Inspector to navigate in the UI.
Here is what I got :

(*set SYM to text returned of (display dialog "Enter Symbol for Stock " default answer "")
display dialog SYM
activate application "Safari"
tell application "Safari"
	open location "www.finance.yahoo.com"
	delay 5 --to allow the page to load	
*)
set SYM to "$"
tell application "System Events"
	tell process "Safari"
		set frontmost to true
		(*	select group 1 of text field 1 of group 1 of group 2 of UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window 1
		*)
		tell window 1
			class of UI elements --> {splitter group, button, button, button, tab, button, group, toolbar}
			tell splitter group 1
				class of UI elements --> {splitter, tab}
				tell UI element 2 -- tab 1 or tab group 1 doesn't compile.
					class of UI elements --> {group}
					tell group 1
						class of UI elements --> {group}
						tell group 1
							class of UI elements --> {scroll area}
							tell scroll area 1
								class of UI elements --> {UI element, scroll bar}
								tell UI element 1
									class of UI elements --> {group, group, group, group, group, group, UI element, group, UI element, group, group, group, group, group, UI element, list, group, UI element, group, group, list, group, UI element, group, group, list, group, UI element, group, group, group, UI element, group, group, group, group, group, group}
									(*
									tell group 2 # Here it's not the correct group to trigger
										class of UI elements --> {}
									end tell
									*)
									tell group 1
										class of UI elements --> {group, group, group, group, group, group, group, group, group, group, group}
										tell group 1
											class of UI elements --> {group}
										end tell
										tell group 2
											class of UI elements --> {UI element, static text, group, group, group, group}
											tell static text 1
												class of UI elements --> {static text}
												properties --> {minimum value:missing value, orientation:missing value, position:{1214, 162}, class:static text, accessibility description:"", role description:"texte", focused:false, title:"", size:{1, 1}, help:"", entire contents:{}, enabled:true, maximum value:missing value, role:"AXStaticText", value:"Search", subrole:missing value, selected:false, name:"Search", description:""}
											end tell
										end tell
									end tell
									
									
									
								end tell
							end tell
						end tell
					end tell
				end tell
			end tell
		end tell
		(*
		--keystroke "l" using command down
		set value of group 1 of text field 1 of group 1 of group 2 of UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window 1 to SYM
		*)
	end tell
end tell
--end tell

I must add that here in France (probably in entire Europe) when the app try to enter Yahoo I get an extraneous page dedicated to the RGPD (https://www.cnil.fr/fr/reglement-europeen-protection-donnees).

Yvan KOENIG running High Sierra 10.13.5 in French (VALLAURIS, France) samedi 7 juillet 2018 18:27:01

Hi Yvan

First thank you. Unfortunately your scrip produced an error.

However I have progressed some, I am stuck at entering the 1st date for the historical data I want. In the scrip below I have hard keyed a date that when it works I would ask the operator for.

Interestingly when I run the scrip I wind up wit the diaolg box open and another window that looks like it is a result of a lookup. I copied it but cannot see how I can attach it to this post.

Thanks

Peter

tell application "Safari" --Makes sure Safari Closed
	quit
end tell
set SYM to text returned of (display dialog "Enter Symbol for Stock " default answer "")
--display dialog SYM
activate application "Safari"
tell application "System Events"
	tell process "Safari"
		set value of text field 1 of UI element 1 of group 4 of toolbar 1 of window "Favorites" to "finance.yahoo"
		delay 5
		tell application "System Events" to key code 36 --return
		set value of text field 1 of group 1 of group 2 of UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window 1 to SYM
		delay 2
		tell application "System Events" to key code 36 --return
		delay 5
		--To Select Historical data
		select text field 1 of group 1 of group 2 of UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window 1
		tell application "System Events" to key code 36 --return
		delay 5
		select group 9 of group 1 of group 8 of UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window 1
		click group 9 of group 1 of group 8 of UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window 1
		--display dialog " Historical Data selected" & return & "Now Select Date Range, this is supposed opens the range to be change	"
		delay 5
		
		click group 1 of text field 1 of group 1 of group 2 of group 9 of UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window 1
		--An attempt to see if it works will have to provided the dates manually
		
		perform action "AXShowMenu" of group 1 of text field 1 of group 1 of group 2 of group 9 of UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window 1
		set value of group 1 of text field 1 of group 10 of group 1 of group 2 of group 9 of UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window 1 to "6/6/2014"
		
	end tell
	
end tell

Really puzzling, here my script behaved flawlessly - of course if the page finance.yahoo was already open.

I added the instructions opening the page and the events log was :


# CAUTION, this is not a script but the events log issued when I run my script.

tell application "Safari"
	activate
	open location "www.finance.yahoo.com"
end tell
tell application "System Events"
	set frontmost of process "Safari" to true
	get class of every UI element of window 1 of process "Safari"
		--> {splitter group, button, button, button, tab, button, group, toolbar}
	get class of every UI element of splitter group 1 of window 1 of process "Safari"
		--> {splitter, tab}
	get class of every UI element of UI element 2 of splitter group 1 of window 1 of process "Safari"
		--> {group}
	get class of every UI element of group 1 of UI element 2 of splitter group 1 of window 1 of process "Safari"
		--> {group}
	get class of every UI element of group 1 of group 1 of UI element 2 of splitter group 1 of window 1 of process "Safari"
		--> {scroll area}
	get class of every UI element of scroll area 1 of group 1 of group 1 of UI element 2 of splitter group 1 of window 1 of process "Safari"
		--> {UI element}
	get class of every UI element of UI element 1 of scroll area 1 of group 1 of group 1 of UI element 2 of splitter group 1 of window 1 of process "Safari"
		--> {group, group}
	get class of every UI element of group 1 of UI element 1 of scroll area 1 of group 1 of group 1 of UI element 2 of splitter group 1 of window 1 of process "Safari"
		--> {group, group, group, group, group, group, group, group, group, group, group}
	get class of every UI element of group 1 of group 1 of UI element 1 of scroll area 1 of group 1 of group 1 of UI element 2 of splitter group 1 of window 1 of process "Safari"
		--> {group}
	get class of every UI element of group 2 of group 1 of UI element 1 of scroll area 1 of group 1 of group 1 of UI element 2 of splitter group 1 of window 1 of process "Safari"
		--> {UI element, static text, group, group, group, group}
	get class of every UI element of static text 1 of group 2 of group 1 of UI element 1 of scroll area 1 of group 1 of group 1 of UI element 2 of splitter group 1 of window 1 of process "Safari"
		--> {static text}
	get properties of static text 1 of group 2 of group 1 of UI element 1 of scroll area 1 of group 1 of group 1 of UI element 2 of splitter group 1 of window 1 of process "Safari"
		--> {minimum value:missing value, orientation:missing value, position:{1313, 143}, class:static text, accessibility description:"", role description:"texte", focused:false, title:"", size:{2, 1}, help:"", entire contents:{}, enabled:true, maximum value:missing value, role:"AXStaticText", value:"Search", subrole:missing value, selected:false, name:"Search", description:""}
end tell
Résultat :
{minimum value:missing value, orientation:missing value, position:{1313, 143}, class:static text, accessibility description:"", role description:"texte", focused:false, title:"", size:{2, 1}, help:"", entire contents:{}, enabled:true, maximum value:missing value, role:"AXStaticText", value:"Search", subrole:missing value, selected:false, name:"Search", description:""}

Yvan KOENIG running High Sierra 10.13.5 in French (VALLAURIS, France) dimanche 8 juillet 2018 18:01:20

Hi Yvan

M maybe its my system, but havoc made sure Safari was closed ran your scrip again and still get this error.

Result:
error “System Events got an error: Can’t get group 1 of group 1 of UI element 2 of splitter group 1 of window 1 of process "Safari". Invalid index.” number -1719 from group 1 of group 1 of UI element 2 of splitter group 1 of window 1 of process “Safari”

As I said I am now past the initial problem and would appreciate any suggestions you have regarding my last scrip which stalls on the drop down box for dates.

Peter

Which system are you running ?
Here your script fails on the instruction

set value of text field 1 of UI element 1 of group 4 of toolbar 1 of window "Favorites" to "finance.yahoo"

It issue the message

error "Erreur dans System Events : Il est impossible de régler window \"Favorites\" of process \"Safari\" à \"finance.yahoo\"." number -10006 from window "Favorites" of process "Safari"

Yvan KOENIG running High Sierra 10.13.5 in French (VALLAURIS, France) dimanche 8 juillet 2018 20:10:32

Hi Yvan

Thanks yet again, I am using 10:13:5

Strange that line works on mine. I am working on a project to save my emails and have a similar problem, in fact I thought I had it working but went to look at it in connection with my current issue as its all to do with drop down lists. What follows is some of what I have so far, it is the part that should allow the email to be saved as a PDF file. But it also stalls on the dropdown list, When the PDF box is selected (that works) I cannot then get it to select the “Save As PDF…” (the end is an ellipse not dots). You can see in the script below that I have tried a number of possibilities, looks like an index error but cannot figure out where.

Thanks

Peter


tell application "Mail"
	tell application "System Events" to set frontmost of process "Mail" to true
	set visible of windows to true
	tell application "System Events"
		tell process "Mail"
			keystroke "p" using command down --Instructs for file to Print
			repeat until exists sheet 1 of window 1 --Loops until the Print Dialog appears
				delay 0.2
			end repeat
			display dialog "in Print Window"
			tell sheet 1 of window 1
				click menu button "PDF" --One of the Options in the Print Dialog Box
				repeat until exists menu 1 of menu button "PDF" --Loops until the menu drop down of PF appears
					delay 0.02
				end repeat
				delay 1
				--click menu item "Save as PDF…"
				--click menu item "Save as PDF…" of menu button "PDF" --Menu Item Selected
				--click menu item "Save as PDF…" of menu 1 of menu button "PDF" of sheet 1 of window 1 of window 1
				--click menu item "Save as PDF…" of menu 1 of menu button "PDF" of sheet 1 of sheet 1 of window 1 --Menu Item Selected
				click menu item "Save as PDF…" of menu 1 of menu button "PDF" --Menu Item Selected
			end tell
			repeat until exists (sheet 1 of sheet 1 of window 1)
				delay 0.2
			end repeat
		end tell
	end tell
end tell

Here I had to edit it as below to get it running.


tell application "Mail"
	activate
	
	--tell application "System Events" to set frontmost of process "Mail" to true
	--set visible of windows to true
end tell

tell application "System Events"
	tell process "Mail"
		set frontmost to true
		keystroke "p" using command down --Instructs for file to Print
		repeat until exists sheet 1 of window 1 --Loops until the Print Dialog appears
			delay 0.2
		end repeat
		--display dialog "in Print Window"
		tell sheet 1 of window 1
			repeat until exists menu button "PDF" -- I found some mails for which this loop is required !
				delay 0.2
			end repeat
			click menu button "PDF" --One of the Options in the Print Dialog Box
			repeat until exists menu 1 of menu button "PDF" --Loops until the menu drop down of PF appears
				delay 0.02
			end repeat
			--delay 1
			
			tell menu 1 of menu button "PDF"
				if exists menu item "Save as PDF…" then
					click menu item "Save as PDF…" --Menu Item Selected
				else
					click menu item "Enregistrer au format PDF"
				end if
			end tell
		end tell
		repeat until exists (sheet 1 of sheet 1 of window 1)
			delay 0.2
		end repeat
	end tell
end tell
--end tell

When the instruction “set visible of windows to true” was active", the script displayed a dialog asking for PDF security parameters.

I added a test allowing it to work on a french system.
In real life i don’t do that, I use a single instruction:

click menu item 2 of menu 1 of menu button "PDF" --Menu Item Selected

or

click (first menu item of menu 1 of menu button "PDF" whose title contains "PDF")

so the script is no longer localisation dependent.

Yvan KOENIG running High Sierra 10.13.5 in French (VALLAURIS, France) lundi 9 juillet 2018 16:50:14

It depends on:

  1. Whether or not Safari currently has a window open called “Favorites”.
  2. How the user’s customised the Safari window toolbar. (See post #2.)
  3. Whether the “Address and Search” field contains a ‘text field’ or a ‘static text’. (Ditto.)

Using ‘open location’ as in post #3 gets round the problem, although of course Safari’s scripting implementation also allows the URL to be set directly, eg.:

tell application "Safari"
	set URL of document 1 to "https://finance.yahoo.com"
end tell

Or:

tell application "Safari"
	make new tab at end of tabs of window 1 with properties {URL:"https://finance.yahoo.com"}
end tell

Or:

tell application "Safari"
	make new document with properties {URL:"https://finance.yahoo.com"}
end tell

When I view the page, the UI element for the search field is:

I don’t know what codes you enter and what pages you go to after that, but it might turn out to be simpler to analyse the URLs the site uses to take you to the pages you want and to have the script generate them itself.

What’s your endgame here? What’s the intended functionality of the script?

If you’re trying to retrieve stock data programmatically, no offense intended, but my first reaction to this is “you’re doing it wrong.”

Don’t try to UI script a browser session.
Use a free API for retrieving stock data.

Here’s one:
https://www.alphavantage.co/documentation/
but you can Google up others.

Like @t.spoon I am curious to what page you are trying to end up with your script? It seems like you’re wanting to go to Yahoo Finance and search for a user input stock symbol.

If this is the case, then as Nigel mentions, it would be easier to look at Yahoo’s URLs and see if you can just pass through the correct URL that you would get back with using the yahoo search bar.

When I look up AMZN it returns this URL:
https://finance.yahoo.com/quote/AMZN

Your script could easily create the URL to pass to Safari to open. Example:


set SYM to text returned of (display dialog "Enter Symbol for Stock " default answer "")
	
tell application "Safari"
	activate
	open location "https://finance.yahoo.com/quote/" & SYM
end tell

If you’re wanting to interact with a symbol’s data from those pages then there is more to it after that. T.Spoon’s API recommendation is a good one. They provided a sample URL to retrieve data from their API:
https://www.alphavantage.co/query?function=BATCH_QUOTES_US&symbols=MSFT,FB,AAPL&apikey=demo

This returns JSON data that is easily parsed and interacted with in AppleScript.

Or using the global/system URL handler (read: using the GURLGURL AppleEvent):

set SYM to text returned of (display dialog "Enter Symbol for Stock " default answer "")
open location "https://finance.yahoo.com/quote/" & SYM

The site wil open in the default browser.