class Finviz::TickersFetcher

Fetch the list of tickers basing on the provided uri or array of filters

Attributes

uri[R]

Public Class Methods

new(uri: nil, filters: [], **rest) click to toggle source
# File lib/finviz/tickers_fetcher.rb, line 8
def initialize(uri: nil, filters: [], **rest)
  raise("You should provide either uri or filters") if uri.present? && filters.present?
  raise("Do not support option #{rest.keys}") unless rest.empty?

  normalize_uri(uri, filters)
end

Public Instance Methods

call() click to toggle source
# File lib/finviz/tickers_fetcher.rb, line 15
def call
  all_pages = first_page + remaining_pages
  all_pages
    .map { |p| p.html.css("table span[onclick]") }
    .flatten
    .map { |a| a.children.text.gsub(/[[:space:]]+/, "") }
end

Private Instance Methods

base_path() click to toggle source
# File lib/finviz/tickers_fetcher.rb, line 61
def base_path
  "/screener.ashx"
end
base_uri() click to toggle source
# File lib/finviz/tickers_fetcher.rb, line 57
def base_uri
  "finviz.com"
end
finviz_view_type() click to toggle source

Output only tickers to reduce pages count

# File lib/finviz/tickers_fetcher.rb, line 66
def finviz_view_type
  411
end
first_page() click to toggle source
# File lib/finviz/tickers_fetcher.rb, line 25
def first_page
  @first_page ||= Crawler.call(paths: uri)
end
generate_further_pages(number) click to toggle source
# File lib/finviz/tickers_fetcher.rb, line 76
def generate_further_pages(number)
  (1...number).map do |i|
    uri.dup.tap do |inner_uri|
      new_query_ar = URI.decode_www_form(inner_uri.query) << ["r", i * per_page + 1]
      inner_uri.query = URI.encode_www_form(new_query_ar)
    end
  end
end
normalize_uri(uri, filters) click to toggle source
# File lib/finviz/tickers_fetcher.rb, line 39
def normalize_uri(uri, filters)
  uri = URI(uri || base_uri)

  @uri = URI::HTTPS.build(
    host: base_uri,
    path: base_path,
    query: CGI.unescape(URI.encode_www_form(query(uri, filters)))
  )
end
per_page() click to toggle source

In tickers view we can get 1k of tickers per request. It is hardcoded be finviz

# File lib/finviz/tickers_fetcher.rb, line 72
def per_page
  1_000
end
query(uri, filters) click to toggle source
# File lib/finviz/tickers_fetcher.rb, line 49
def query(uri, filters)
  CGI.parse(uri.query || "").tap do |params|
    params["f"] = filters.join(",") if filters&.any?
    params["v"] = finviz_view_type
    params.delete("r") # remove offset if it was provided
  end
end
remaining_pages() click to toggle source
# File lib/finviz/tickers_fetcher.rb, line 29
def remaining_pages
  return @remaining_pages if @remaining_pages

  max_page = first_page.first.html.css("a.screener-pages").map { |a| a.children.text.to_i }.max
  return @remaining_pages = [] unless max_page

  paths = generate_further_pages(max_page)
  @remaining_pages = Crawler.call(paths: paths)
end