Need a reference for a simple real-time or same-day close fund prices


Ever since Yahoo! killed their stock quotes and Numbers did as well, I’m looking for a one-shot URL to get a set of 3 mutual fund end-of-session but same-day quotes. I could trigger this from a launchd plist.

Something of the nature of http :// www.,BBBB,CCCC that would return the 3 values.

Any suggestions? The ones I have found are way too complicated.

(cobbap) #2

Numbers killed their stock quotes? In Numbers – =STOCK(“aapl”) returns today’s Apple closing stock price.


I get $178.39, which is YESTERDAY’s closing price. Today’s close is $178.12 . This is expected, as it was announced in the forums and explained in the new version of Numbers.

Anyone else have a suggestion for getting 3 fund values? I have several lines of code that seemed to almost work before Yahoo! killed their stock API. Looking for a replacement. The ones I have found want to send me reams of info - all I want is the closing price.

(Ed Stockly) #4

Try this:

You need to create an account, not sure if they charge.

(Vince Angeloni) #5

You need to learn to do a little web scraping for this. MacScripter’s ‘unscripted’ section has a tutorial on one way to do it (see URL below). I posted a comment several years ago on this article that referenced using a Ruby gem web-scraper which seemed to make it a bit easier to do, at least for me. ymmv.

Macscripter HTML parsing (web scraping)

(Jim Underwood) #6

I agree with that, but I have found that using JavaScript injection in the Browser (Safari or Chrome) is easier and more effective.

There are a variety of JavaScript tools to find/select the HTML of interest.

  • There are the traditional getElementsBy
  • I prefer document.querySelector
  • and use of XPath.
  • and more.

A huge advantage is that you can use Chrome “Inspect” tool on the text/object of interest on the web page, and then use the JavaScript Console to develop/test the JavaScript statements you need to use. The Chrome JavaScript Console provides great support, including very intelligent, easy-to-use autocompletion and debugging.

(Vince Angeloni) #7

Heh - several years = 2011! Time flies…
I didn’t really ever do anything with this, except play around with one Ruby script for grins, but I think what I am suggesting in my comment on the Macscripter article is very similar to what Jim is suggesting. I also noticed that the link I included in that comment is way dead…now that seems to be a jewelry blog or something! Fortunately, I did save the tutorial from the link in a PDF showing how to use Nokogiri to web scrape, if you want to look at it: Web Scraping with Nokogiri


Re: Marketwatch, they’re great but I don’t see an API on their main page. Anyone know what it is?

For example,

set fundPrices to do shell script (“curl,TLIRX,QREARX”) //rough idea

or similar.

(Ed Stockly) #9

Here’s a script that Shane and Jim posted here a while back that I’ve been using for downloading web pages to scrape. This version get text from market watch that you can parse to get the closing value of the specific stock or index.

set pageURLStr to ""

  PURPOSE: Get Web Page HTML using ASObjC
              (as an alternate to curl)
  REF:  Script posted by @ShaneStanley to ASUL, 2017-03-31 
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions


set pageURLnsStr to current application's NSString's stringWithString:pageURLStr
set nsPageURL to current application's NSURL's URLWithString:pageURLnsStr


set {nsPageHTML, theError} to current application's NSData's dataWithContentsOfURL:nsPageURL options:0 |error|:(reference)
if nsPageHTML = missing value then error (theError's localizedDescription() as text)

-- convert to XML

set {theXMLDoc, theError} to current application's NSXMLDocument's alloc()'s initWithData:nsPageHTML options:(current application's NSXMLDocumentTidyHTML) |error|:(reference)
if theXMLDoc = missing value then error (theError's localizedDescription() as text)

--    • As an alternate to JavaScript in the Browser, use ASObjC XML methods
--    • For an example, see 

--  • There are several options to choose from
--     SEE: Writing XML From NSXML Objects

-- 1. SIMPLE
set htmlSimpleStr to theXMLDoc's XMLString() as text

-- 2. TIDY
set htmlTidyStr to (theXMLDoc's XMLStringWithOptions:(current application's NSXMLDocumentTidyHTML)) as text

-- (I don't see any difference between #1 and #2)

-- 3. PRETTY PRINT (produces a very readable XML/HTML output)
set htmlPPStr to (theXMLDoc's XMLStringWithOptions:(current application's NSXMLNodePrettyPrint)) as text

(Shane Stanley) #10

Or skipping the text and using XPath to get the price:

set thePrice to (theXMLDoc's nodesForXPath:"//meta[@name='price']/attribute::content" |error|:(missing value))'s firstObject()'s stringValue() as text

(Jim Underwood) #11

Thanks Shane for a great example.

To Those Interested in Learning about XPath:

Defining a XPath can be challenging, but in this case it is straight-forward.

All of the HTML meta tags are in the <header>. . .</header> block. So with the web page open in Chrome, press ⌘⌥I to open the Chrome Dev Tools showing the HTML elements of the page. Expand the <header> block to view its elements.

You can either visually scan for the meta tag of interest, or use Find (⌘F), in this case for “price”. It is the second occurance found:


While “name” and “content” are the most common key/value pairs, sometimes other attributes are used. So you may need to adjust accordingly.

For more info, see XPath in Javascript: Introduction

While there is very little on the web about using XPath with ASObjC, there is a lot about using it with JavaScript. So you may need to search for JavaScript examples, then translate them to ASObjC, if that’s your preferred tool.

(Shane Stanley) #12

That’s true, but XPath is XPath wherever you use it. I don’t use it often enough to remember, so I generally start here:

The nodesForXPath:error: method simply returns an array of matching NSXMLNodes. In this case firstObject() gets the first (and only in this case) node in the array, and stringValue() is how you extract the string from an attribute node.