UNPKG

node-finviz-screener

Version:

Simple package that takes a url for a finviz stock screener and returns a list of tickers that pass the screen

58 lines (48 loc) 1.87 kB
const fetch = require("node-fetch"); const cheerio = require("cheerio"); const TICKERS_SELECTOR = "#screener-content#screener-content > table > tbody > tr:nth-child(4) > td > table > tbody > tr > td:nth-child(2)"; const PAGINATION_SELECTOR = ".screener_pagination"; const FINVIZ_URL_PREPEND = "https://finviz.com/"; const timer = async (ms) => { return new Promise((resolve, reject) => { setTimeout(() => resolve(), ms); }); }; /** * Get a list of tickers that pass a Finviz screen * @param {string} finvizScreenerUrl - the url of the Finviz screener to search for * @returns {string[]|string} array of tickers that pass the Finviz screen, or an error message */ async function getFinvizScreen(finvizScreenerUrl, __tickers = null) { // typeguard try { /(\/\/finviz.com\/screener.ashx)/.exec(finvizScreenerUrl)[0]; } catch (err) { return "ERROR: invalid finviz screener URL. Please pass a valid link to a finviz screener."; } const res = await fetch(finvizScreenerUrl); const text = await res.text(); const $ = cheerio.load(text); const syms = $(TICKERS_SELECTOR) .map(function (i, el) { if (i !== 0) return $(this).text(); // first row is header row ("Ticker") }) .get(); __tickers = __tickers ? __tickers.concat(syms) : syms; const pagination = $(PAGINATION_SELECTOR).children(); // all the other pages to go through const next = pagination.filter(function (i, el) { const text = $(this).text(); return text === "next"; }); if (next.length > 0) { // if there is a 'next' page, go to it await timer(7); // too quick a pace on the requests causes the server to return a blank page with only "too many requests" on it return getFinvizScreen(FINVIZ_URL_PREPEND + next.attr("href"), __tickers); } else { return __tickers; } } module.exports = { getFinvizScreen, };