Nothing too special here but thought it might be useful to someone. I find myself constantly searching google and then command clicking on the first several results to open them in a new tab in Safari. This speeds up that process a little.
It works in Google Chrome and Firefox as well, I haven't tested any other browser. Google Search.zip (61.0 KB)
Tab is not a reliable method of navigating links in Safari on my 10.9.5 system.
This macro will scrape the links out of a Google search page and send them to TextWrangler (although you can change TextWrangler to BBEdit in the script to use BBEdit instead).
It produces a list with the link titles and links formatted in a table like so:
Thanks Chris, you are always a rock star in your approach. I also noticed that with the tab it would often do every other link, which seems very bizarre.
I look forward to seeing your following AppleScript.
I like to position my window in TextWrangler (BBEdit for me) so I can see the edge of it behind Safari. That lets me see the line numbers in TextWrangler to let me know how many more URLs I have to process.
On my system I have plugins for more sites than Google. I use a folder in the Finder to contain scripts named with the base-domain of the site to be searched. So it's relatively easy to add a new site to my link scraper.
Thanks β a useful approach and good food for thought.
For reference, in case it's of any interest, here's one way of opening all the tabs from the shell (after gathering them with JXA (and in-browser) Javascript), and passing them on in Markdown format.
So I had been using this almost daily until I upgraded my Mac and it broke any ideas?
Keyboard Maestro 8.2.2 βHarvest Google result links, opening each in own tabβ Macro
And here is an updated JXA script, which seems to be working on Sierra, with KM 8.2.2 and Safari 11.1.2 (Develop > Allow JavaScript from Apple Events enabled)
(() => {
'use strict';
const main = () => {
const
strXPath = "//*[@class='r']/a",
saf = Application("Safari"),
ws = saf.windows,
lrHarvest = bindLR(
0 < ws.length ? (
Right(ws.at(0))
) : Left('No window open in Safari'),
w => {
const
xs = pageXPathHarvest(
saf, w, strXPath
);
return 0 < xs.length ? (
// Safari effect
tabsOpened(saf, w, xs),
// Keyboard Maestro value
Right(
xs.reduce(
(a, link) =>
`${a}[${link[0]}](${link[1]})\n`,
''
)
)
) : Left(
'Perhaps not a Google search page ?\n' +
'(No links matching "' + strXPath + '")'
);
}
);
return lrHarvest.Left || lrHarvest.Right;
};
// SAFARI ---------------------------------------------
// Harvest elements from Safari by XPath pattern
const pageXPathHarvest = (browser, oWin, strXPath) =>
browser.doJavaScript(
`(${xpathHarvest})("${strXPath}")`, { in
: oWin.currentTab
}
);
// tabsOpened :: Application -> Window -> (String, String) -> IO()
const tabsOpened = (safari, oWin, links) => {
const winTabs = oWin.tabs;
links.map(link => winTabs.push(safari.Tab({
url: link[1]
})))
}
// Harvesting function to run in the browser context
const xpathHarvest = strPath => {
const
r = document.evaluate(strPath, document, null, 0, null),
xs = [];
var oNode;
while (oNode = r.iterateNext()) {
xs.push([oNode.text, oNode.href]);
}
return xs;
};
// GENERIC FUNCTIONS ----------------------------------
// https://github.com/RobTrew/prelude-jxa
// Left :: a -> Either a b
const Left = x => ({
type: 'Either',
Left: x
});
// Right :: b -> Either a b
const Right = x => ({
type: 'Either',
Right: x
});
// bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
const bindLR = (m, mf) =>
m.Right !== undefined ? (
mf(m.Right)
) : m;
// MAIN
return main();
})();
I did activate: Develop > Allow JavaScript from Apple Events enabled
Perhaps I am missing something and this is not what the script does. It's just the AppleScript I was using made by @ccstone is failing in Sierra and above now.
Here is the error I get when I run it:
/var/folders/5l/5s7qw5ld1xxglm0094_hyh_c0000gn/T/Keyboard-Maestro-Script-81ECA7A6-72E3-4B9E-B603-D65552A765FE:5:6: script error: Expected expression but found β>β. (-2741)
This one works in that it opens all the links in new tabs. I just wanted a script that will open first link only in current tab.
And a way to specify which link to open in the script so I can have 4 different hotkeys for opening either 1st or 2nd or 3rd or 4th link with a macro for each one.
Got it β so what you need, in place of the tabsOpened function, is something like:
// nthLinkOpened :: Application -> (String, String) -> Int -> IO()
const nthLinkOpened = (safari, links, i) => {
const
ds = safari.documents,
d = ( // Ensuring that there is an open document
ds.length < 1 && ds.push(safari.Document()),
ds.at(0)
);
// i is a zero-based index into the link list.
return d.url = links[i][1];
};