@user3439894's answer is excellent, and he's shown you some good, robust techniques for determining whether a webpage has loaded; some elementary JavaScript; and the power of awk
.
I decided to do it a different way. I use JavaScript to do all the heavy processing, largely because my ultimate goal was to obtain a list of record
objects, each representing a single event listed on the webpage, from which I extracted the name, location and time of each event.
tell application id "com.apple.Safari" to tell ¬
document 1 to set allEvents to do JavaScript ¬
"Array.from(document
.querySelectorAll('tbody#meetings_tbody '+
'tr '+
'td.name,'+
'td.time,'+
'td.location'))
.reduce((ξ,x,i,L) => {
ξ=Array.from(ξ);
i%3==1 && ξ.push({
'name': L[i].innerText,
'time': L[i-1].innerText,
'location': L[i+1].innerText
});
return ξ;
});"
The variable allEvents
should then contain something like this:
{{|name|:"Saturday @ 7", |time|:"7:00 am", location:"Token 3 Club"},
{|name|:"Early Bird Meeting", |time|:"8:00 am", location:"Token 3 Club"},
{|name|:"Saturday Morning Meditation Group", |time|:"8:30 am", location:"Christ Church United Methodist"},
{|name|:"Saturday Morning Gratitude Group", |time|:"8:30 am", location:"Icehouse"},
...,
{|name|:"Agape", |time|:"10:30 pm", location:"Token 3 Club"}}
I'm not sure how familiar you are with AppleScript list
or record
objects. If you examine the contents carefully, you'll see that each event is represented by an object that looks like this:
{|name|:"...", |time|:"...", location:"..."}
That is a record
, which contains three properties
: |name|
, |time|
, and location
. Each property
has a value, which you retrieve by referencing the <property> of <record>
. So, if one creates a record object and assigns it to a variable thus:
set R to {a:1, b:"two", c:pi}
then:
set myvar to b of R
will retrieve the value of property b
belonging to record R
and store it in the variable myvar
. So myvar
will now evaluate to "two"
.
allEvents
isn't just one record
object; it's many. It's a list
of them. Here's an example of a list:
set L to {1, "two", pi, 2^2, "5.0"}
It doesn't contain properties; it only contains values, and these are termed items
. A list
is held in strict order, whereas a record
is not. Therefore, the value "two"
will always appear as the second item
in that list, but in the record, it can appear at the beginning, middle, or end, but will always be attached to the property b
. To retrieve an item from a list:
set myvar to item 2 of L
So, skipping to the end somewhat, if you want the location of the 4th event in that list:
return the location of item 4 in allEvents --> "Icehouse"
You'll still want to follow @user3439894's example, and implement a test to determine when the page has loaded (unless you intend to trigger the script manually only after loading the page yourself). @user3439894 has also shown you how to adapt the code to a Chromium-based browser (Google Chrome, Vivaldi, Brave).