I want to make an Apple script to evaluate data

Hi everyone,


I want to make an apple script to evaluate data taken from a website where login is required. I am already having trouble with the first steps...


First I had something, you'll probably laugh about:


tell application "Safari"
open location "http://c108-013.cloud.gwdg.de/accounts/login/?next=/sabo/"

activate
tell application "System Events"
keystroke "test_usr"
delay 3
keystroke return
keystroke "test_pw"
delay 3
keystroke return
end tell

tell application "Safari"
open location "http://c108-013.cloud.gwdg.de/sabo/overview/1"

end tell
end tell


it worked, but it was very unreliable and in the end it messed up all the time.


So now, I have something which is supposed to be neater, but I cannot make it work:


set user_name to "test_usr"
set user_password to "test_pw"

tell application "Safari"
activate
open location "http://c108-013.cloud.gwdg.de/accounts/login/?next=/sabo/"
end tell
#^^this works

to inputByName(theName, theValue)

tell application "Safari"
tell tab 1 of window 1
do JavaScript "
document.getElementByName('username').value=user_name;
document.getElementByName('password').value=user_password;
document.forms[0].submit()
" in document 1
end tell
end tell

end inputByName
#^^nothing happens here


tell application "Safari"
open location "http://c108-013.cloud.gwdg.de/sabo/overview/1"

end tell
#^^this works



Extra infos: The reason why I open a tab, login and then open another one is, that I actually need to navigate from the homepage (after login) through a button to another site. It is not so elegant this way, but it works after I'm logged in.


Maybe I make mistakes in reading the source code to get the elements:






Since I can't find a ID or class, I'm trying to cope with the name of the element...



I have no idea about Javascript or Applescript or any other coding, its probably a stupid mistake...


Happy about any help!



[Re-Titled by Moderator]


Posted on Aug 31, 2021 1:55 PM

Reply
Question marked as Top-ranking reply

Posted on Aug 31, 2021 10:18 PM

Quite simple - your JavaScript code is never called, so Safari doesn't even bother trying to fill out the form.


This is because you embed the JavaScript code inside a handler:


to inputByName(theName, theValue)


This basically folds everything up to the matching end statement into a single command (in this case, inputByName).


However, to actually run this code you have to call the handler somewhere.


Handlers are most useful for writing blocks of code that are called repeatedly through your script, so you only have to write them once and you invoke them by calling their name. In this case, it's a one-off, so you can either invoke the handler, or (even simpler), just remove the handler definition and embed the code directly in the script


In addition to that, if you want to embed the user_name and user_password variables inside the JavaScript, you need to use concatenation to build the command appropriately. As written the line:


				document.getElementByName('username').value=user_name;


will literally call JavaScript passing 'user_name' as the value (which will likely fail since it doesn't represent a quoted string, nor a JavaScript variable.

Instead use something like:


document.getElementByName('username').value="& theName & ";


where this will combine the JavaScript code with the current value of the AppleScript variable.


Option 1: call the handler:


set user_name to "test_usr"
set user_password to "test_pw"

tell application "Safari"
	activate
	-- this opens the login page
	open location "http://c108-013.cloud.gwdg.de/accounts/login/?next=/sabo/"
	
	-- call the handler to fill in the form
	my inputByName(username, user_password)
	
	-- continue the script flow
	open location "http://c108-013.cloud.gwdg.de/sabo/overview/1"
end tell

to inputByName(theName, theValue)
	tell application "Safari"
		tell tab 1 of window 1
			do JavaScript "
				document.getElementByName('username').value="& theName & ";
				document.getElementByName('password').value=" & theValue & ";
				document.forms[0].submit()
				" in document 1
		end tell
	end tell
end inputByName


Option 2: include the form filling in the normal flow:


set user_name to "test_usr"
set user_password to "test_pw"

tell application "Safari"
	activate
	-- this opens the login page
	open location "http://c108-013.cloud.gwdg.de/accounts/login/?next=/sabo/"
	
	--  fill in the form directly
	tell tab 1 of window 1
		do JavaScript "
			document.getElementByName('username').value=" & user_name & ";
			document.getElementByName('password').value=" & user_password & ";
			document.forms[0].submit()
			" in document 1
	end tell
	
	-- continue the script flow
	open location "http://c108-013.cloud.gwdg.de/sabo/overview/1"
end tell



Similar questions

6 replies
Question marked as Top-ranking reply

Aug 31, 2021 10:18 PM in response to fastanonym

Quite simple - your JavaScript code is never called, so Safari doesn't even bother trying to fill out the form.


This is because you embed the JavaScript code inside a handler:


to inputByName(theName, theValue)


This basically folds everything up to the matching end statement into a single command (in this case, inputByName).


However, to actually run this code you have to call the handler somewhere.


Handlers are most useful for writing blocks of code that are called repeatedly through your script, so you only have to write them once and you invoke them by calling their name. In this case, it's a one-off, so you can either invoke the handler, or (even simpler), just remove the handler definition and embed the code directly in the script


In addition to that, if you want to embed the user_name and user_password variables inside the JavaScript, you need to use concatenation to build the command appropriately. As written the line:


				document.getElementByName('username').value=user_name;


will literally call JavaScript passing 'user_name' as the value (which will likely fail since it doesn't represent a quoted string, nor a JavaScript variable.

Instead use something like:


document.getElementByName('username').value="& theName & ";


where this will combine the JavaScript code with the current value of the AppleScript variable.


Option 1: call the handler:


set user_name to "test_usr"
set user_password to "test_pw"

tell application "Safari"
	activate
	-- this opens the login page
	open location "http://c108-013.cloud.gwdg.de/accounts/login/?next=/sabo/"
	
	-- call the handler to fill in the form
	my inputByName(username, user_password)
	
	-- continue the script flow
	open location "http://c108-013.cloud.gwdg.de/sabo/overview/1"
end tell

to inputByName(theName, theValue)
	tell application "Safari"
		tell tab 1 of window 1
			do JavaScript "
				document.getElementByName('username').value="& theName & ";
				document.getElementByName('password').value=" & theValue & ";
				document.forms[0].submit()
				" in document 1
		end tell
	end tell
end inputByName


Option 2: include the form filling in the normal flow:


set user_name to "test_usr"
set user_password to "test_pw"

tell application "Safari"
	activate
	-- this opens the login page
	open location "http://c108-013.cloud.gwdg.de/accounts/login/?next=/sabo/"
	
	--  fill in the form directly
	tell tab 1 of window 1
		do JavaScript "
			document.getElementByName('username').value=" & user_name & ";
			document.getElementByName('password').value=" & user_password & ";
			document.forms[0].submit()
			" in document 1
	end tell
	
	-- continue the script flow
	open location "http://c108-013.cloud.gwdg.de/sabo/overview/1"
end tell



Sep 1, 2021 10:01 AM in response to fastanonym

I guess I needed to dig into JavaScript more. turns out there are two issues there.


The recommended way of setting form values is:


			document.forms[0].elements['element_name'].value='new value';


There are two changes here - one is referencing the form, rather than the entire document. The second is that the value needs to be quoted (in my original example I didn't wrap the value in single quotes). Therefore the JavaScript should look like:


		do JavaScript "
			document.forms[0].elements['username'].value='" & user_name & "';
            document.forms[0].elements['password'].value='" & user_password & "';
	        document.forms[0].submit()"
	end tell


the other thing that you need to check is that you are specifically targeting tab 1 of window 1. This may fail if you have multiple tabs open in this window and it's targeting the first tab while you're looking at the second or third.

Sep 1, 2021 9:00 AM in response to fastanonym

This sounds like a simple race condition.


Normally, AppleScripts will execute as quickly as they can. In this case, the script is telling Safari to open a page, and then immediately tries to fill in the form. More than likely the page hasn't finished loading, and therefore the JavaScript fails because it can't find the form elements.


The simple fix? add a delay statement after the open location command to give the page time to load. You'll need to decide how long to wait to allow the page to load.


open location "https://blah.blah.blah/"
delay 5 -- wait 5 seconds to allow the page to load


There's a more complex solution which involves detecting when the page has finished loading, but a simple delay should be all you need.

Sep 1, 2021 6:31 AM in response to Camelot

Hi Camelot,


first, thank you for your fast reply!


Sadly the code still does not come beyond the point where it opens the login url (in both cases). It also opens the second url, but shows the login page again. So, it still seems to just skips the JavaScrip part. Going with the first suggestion, it looks like this now:


set user_name to "test_usr"
set user_password to "test_pw"

tell application "Safari"
	activate
	
	open location "http://c108-013.cloud.gwdg.de/accounts/login/?next=/sabo/"
	
		do JavaScript "
				document.getElementByName('username').value=" & user_name & ";
				document.getElementByName('password').value=" & user_password & ";
				document.forms[0].submit()
				" in document 1
	
	open location "http://c108-013.cloud.gwdg.de/sabo/overview/1"
end tell


There is no error reported, it just does not fill in the form etc.


Note: I got an error, when I run the code with the line

tell tab 1 of window 1
...
end tell

so I just deleted it.


This was the error:

Saying something like: "Safari" got an error: "document 1 of tab 1 of window 1" can not be read.


It didn't give me the error when ran the previous code with the line above (second code from my first post). Maybe because, the part was not actually executed?

Sep 1, 2021 9:30 AM in response to Camelot

it does not change anything... could it that some needed option in Apple Script or Safari settings is disabled? I have already enabled the 'allow JavaScript on Apple Events'-option, so that can't be it...


Or is there maybe a way to test, if the javascript code has the right element information, so it actually knows, where I want to put the information?


Or could it be that the website is blocking automated login for secure reasons? And how could I find that out if its the case?

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

I want to make an Apple script to evaluate data

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.