Dates from website with user input

Hi,

I was wondering if someone could help me with debugging my script.

My aim is to ask the user for a number and once entered then extract the date associated with that number eg. user input of 997 (Sg:AU 997), with the Sg:AU being the default answer, results in the date 1986-01-24

Current problem is that no matter what number I enter it only results in 1986-02-12. Also, it would be nice to have the cursor sitting at the end of the default answer instead of highlighting it.

My script (apple) so far…

set theResponse to display dialog "Catalogue number?" default answer "Sg:AU " buttons {"Cancel", "Continue"} default button "Continue"
set sgno to (text returned of theResponse)

tell application "Google Chrome"
	repeat with x from 0 to ((execute active tab of first window javascript "document.getElementsByClassName('i_d').length") - 1)
		set theDate to execute active tab of first window javascript "document.getElementsByClassName('i_d')[" & x & "].outerHTML"
		if theDate contains sgno then exit repeat
	end repeat
	set theDate to execute active tab of first window javascript "document.getElementsByTagName('dd')[" & x & "].innerHTML"
end tell

return theDate

And the website I’m using https://colnect.com/en/stamps/list/country/8147-Australia/year/1986

Thank you
l0g0p7

Model: MacBook Pro (Retina, 13-inch, Mid 2014)
Browser: Google Chrome Version 70.0.3538.102 (Official Build) (64-bit)
Operating System: macOS 10.14

Hi. Welcome to MacScripter.

Sorry you don’t seem to have received a reply yet. Presumably no-one here’s familiar with both Chrome and JavaScript.

I’m certainly not expert in either, but I’ve been fooling around in Safari this afternoon and the problem seems to be that the last bit of JavaScript in your script is getting the xth ‘dd’ tag of the document instead of the fourth ‘dd’ tag (ie. no. 3) of the xth ‘i_d’ object. If your Chrome syntax is correct, this should work:

set theResponse to display dialog "Catalogue number?" default answer "Sg:AU " buttons {"Cancel", "Continue"} default button "Continue"
set sgno to (text returned of theResponse)

tell application "Google Chrome"
	repeat with x from 0 to ((execute active tab of first window javascript "document.getElementsByClassName('i_d').length") - 1)
		set i_dHTML to (execute active tab of first window javascript "document.getElementsByClassName('i_d')[" & x & "].outerHTML")
		if (i_dHTML contains sgno) then
			set theDate to (execute active tab of first window javascript "document.getElementsByClassName('i_d')[" & x & "].getElementsByTagName('dd')[3].innerHTML")
			return theDate
		end if
	end repeat
end tell

Another idea, if it works in Chrome, would be to do the whole search in JavaScript:

set jsCode to "idCount = document.getElementsByClassName('i_d').length
	x = 0
	theDate = ''
	do {
		id = document.getElementsByClassName('i_d')[x]
		found = (id.outerHTML.indexOf('" & sgno & "') >= 0)
		if (found) {
			theDate = id.getElementsByTagName('dd')[3].innerHTML
		}
		x = x + 1
	}
	while ((!found) && (x < idCount))
	
	theDate"

tell application "Google Chrome" to set theDate to (execute active tab of first window javascript jsCode)

The Safari versions of the above were tested by entering just the number or "AU " and the number into the dialog. “sg:AU” doesn’t occur as a continuous string in the ‘i_d’ object’s outerHTML, so if that’s entered, the object won’t be identified.

Hi Nigel,

Thank you for your welcome and your reply. They are both greatly appreciated. Your script worked great. Thank you so much :slight_smile:

I did have to change to default answer to "Sg:AU " so that the script would return the correct date. Whereas with just the AU it sometimes could return a different result other than the one I wanted as there are sometimes different options for the same number.

But thank you, all the same, I really appreciate your help
Thank you again
l0g0p7

P.S. I haven’t tried the javascript as I have almost no knowledge there

Here is the final/working AppleScript for anyone to use.


set theResponse to display dialog "Catalogue number?" default answer "<strong>Sg:</strong>AU " buttons {"Cancel", "Continue"} default button "Continue"
set sgno to (text returned of theResponse)

tell application "Google Chrome"
	repeat with x from 0 to ((execute active tab of first window javascript "document.getElementsByClassName('i_d').length") - 1)
		set i_dHTML to (execute active tab of first window javascript "document.getElementsByClassName('i_d')[" & x & "].outerHTML")
		if (i_dHTML contains sgno) then
			set theDate to (execute active tab of first window javascript "document.getElementsByClassName('i_d')[" & x & "].getElementsByTagName('dd')[3].innerHTML")
			--return theDate
			set the clipboard to theDate
		end if
	end repeat
end tell

tell application "Numbers" to activate
tell application "System Events"
	tell process "Numbers"
		keystroke "v" using {command down, option down, shift down}
		key code 36
	end tell
end tell

hi and welcome

I have added to the beginning of your script some code that will place the cursor in front of you default text in the dialog displayed.

set DefaultAnswer to "AU"
do shell script "osascript -e 'tell application \"System Events\" to key code 124' > /dev/null 2>&1 & " -- Right arrow keystroke
set sgno to text returned of (display dialog "Catalogue number?" default answer DefaultAnswer & " " buttons {"Cancel", "Continue"} default button "Continue")

tell application "Google Chrome"
	repeat with x from 0 to ((execute active tab of first window javascript "document.getElementsByClassName('i_d').length") - 1)
		set i_dHTML to (execute active tab of first window javascript "document.getElementsByClassName('i_d')[" & x & "].outerHTML")
		if (i_dHTML contains sgno) then
			set theDate to (execute active tab of first window javascript "document.getElementsByClassName('i_d')[" & x & "].getElementsByTagName('dd')[3].innerHTML")
			set the clipboard to theDate
		end if
	end repeat
end tell

tell application "Numbers" to activate
tell application "System Events"
	tell process "Numbers"
		keystroke "v" using {command down, option down, shift down}
		key code 36
	end tell
end tell 

Thank you Budgie for you help that works great :slight_smile:

I really appreciate it

There is one little thing though.

I have occasionally come a cropper with getting some of the dates as the placement of the date isn’t always in position 3 (as using in the script). I can sometimes be in the 4th position. is there anything that can be done to help fix that?

set theDate to (execute active tab of first window javascript "document.getElementsByClassName('i_d')[" & x & "].getElementsByTagName('dd')[3].innerHTML")

I was thinking of somehow using the itemprop=“releaseDate” from

1990-02-17
. but haven’t had any success figuring out how

Thank you again
l0g0p7

:cool:

Not knowing a lot about JavaScript, I’d personally find it easiest to parse the HTML with regex in ASObjC, although I imagine it’s doable in JavaScript. The following uses JavaScript to get the outerHTML of each ‘i_d’ object and ASObjC to parse it. If I knew how to extract the source code for the entire page in Chrome, I’d use ASObjC to parse that too.

use AppleScript version "2.4" -- Mac OS 10.10 (Yosemite) or later.
use framework "Foundation"
use scripting additions

on getDateFromPage()
	do shell script "osascript -e 'tell application \"System Events\" to key code 124' > /dev/null 2>&1 & " -- Right arrow keystroke
	-- Get the user input in a form where they don't have to think about the HTML.
	set theResponse to display dialog "Catalogue number?" default answer "Sg:AU " buttons {"Cancel", "Continue"} default button "Continue"
	set sgno to (text returned of theResponse)
	-- Massage the input into a usable search string, assuming no errors or extraneous spaces.
	if (sgno begins with "Sg:") then
		set sgno to "<strong>Sg:</strong>" & text 4 thru -1 of sgno
	else if (sgno begins with "AU") then
		set sgno to "<strong>Sg:</strong>" & sgno
	else -- Assume only the number's been given.
		set sgno to "<strong>Sg:</strong>AU " & sgno
	end if
	-- Preset a regex (as an NSString) matching the search string followed by either a comma or "<".
	set sgno to current application's class "NSString"'s stringWithString:(sgno & "[,<]")
	set regexSearch to current application's NSRegularExpressionSearch
	
	tell application "Google Chrome"
		repeat with x from 0 to ((execute active tab of first window javascript "document.getElementsByClassName('i_d').length") - 1)
			set i_dHTML to (execute active tab of first window javascript "document.getElementsByClassName('i_d')[" & x & "].outerHTML")
			-- Get an NSString version of the JavaScript result and parse it using regex in ASObjC.
			set i_dHTML to (current application's class "NSString"'s stringWithString:(i_dHTML))
			if ((i_dHTML's rangeOfString:(sgno) options:(regexSearch))'s |length| > 0) then
				set dateRange to (i_dHTML's rangeOfString:("(?<=<dd itemprop=\"releaseDate\">)[^<]++") options:(regexSearch))
				set theDate to (i_dHTML's substringWithRange:(dateRange)) as text
				set the clipboard to theDate
				exit repeat
			end if
		end repeat
	end tell
end getDateFromPage

getDateFromPage()

-- Numbers stuff here.

Edits: Code put in a handler to make the variables local and therefore non-persistent. (ASObjC values can’t be saved in script files.) Application corrected to Google Chrome!

Wow!!! Thank you so much, Nigel. Amazing work :slight_smile: :slight_smile:

I’ve just tested it and it’s working wonderfully. I use Automator and turn it into a service so I can attach a keyboard shortcut to it. I’ll let you know if anything else happens but its working great.

Thank you both so much for all your help.
l0g0p7