Module: Html2rss::AutoSource::Scraper
- Defined in:
- lib/html2rss/auto_source/scraper.rb,
lib/html2rss/auto_source/scraper/html.rb,
lib/html2rss/auto_source/scraper/schema.rb,
lib/html2rss/auto_source/scraper/sitemap.rb,
lib/html2rss/auto_source/scraper/microdata.rb,
lib/html2rss/auto_source/scraper/json_state.rb,
lib/html2rss/auto_source/scraper/meta_oembed.rb,
lib/html2rss/auto_source/scraper/schema/thing.rb,
lib/html2rss/auto_source/scraper/xhr_articles.rb,
lib/html2rss/auto_source/scraper/microformats2.rb,
lib/html2rss/auto_source/scraper/semantic_html.rb,
lib/html2rss/auto_source/scraper/wordpress_api.rb,
lib/html2rss/auto_source/scraper/sitemap/parser.rb,
lib/html2rss/auto_source/scraper/schema/item_list.rb,
lib/html2rss/auto_source/scraper/json_state/value_finder.rb,
lib/html2rss/auto_source/scraper/wordpress_api/page_scope.rb,
lib/html2rss/auto_source/scraper/schema/category_extractor.rb,
lib/html2rss/auto_source/scraper/json_state/document_scanner.rb,
lib/html2rss/auto_source/scraper/wordpress_api/posts_endpoint.rb,
lib/html2rss/auto_source/scraper/json_state/article_normalizer.rb,
lib/html2rss/auto_source/scraper/json_state/candidate_detector.rb,
lib/html2rss/auto_source/scraper/semantic_html/entry_deduplicator.rb,
lib/html2rss/auto_source/scraper/wordpress_api/page_scope/date_archive_range.rb
Overview
The Scraper module contains all scrapers that can be used to extract articles.
Each scraper should implement an each method that yields article hashes.
Each scraper should also implement an articles? method that returns true if the scraper
can potentially be used to extract articles from the given HTML.
Detection is intentionally shallow for most scrapers, but instance-based matching is available for scrapers that need to carry expensive selection state forward into extraction.
Defined Under Namespace
Classes: Html, JsonState, MetaOembed, Microdata, Microformats2, NoScraperFound, Schema, SemanticHtml, Sitemap, WordpressApi, XhrArticles
Constant Summary collapse
- APP_SHELL_ROOT_SELECTORS =
Root markers indicating likely app-shell/client-rendered surfaces.
'#app, #root, #__next, [data-reactroot], [ng-app], [id*="app-shell"]'- APP_SHELL_MAX_ANCHORS =
Maximum anchors tolerated before app-shell detection is considered unlikely.
2- APP_SHELL_MAX_VISIBLE_TEXT_LENGTH =
Maximum visible text length tolerated for app-shell classification.
220- SCRAPER_TIERS =
Extraction tiers: merge within a tier, then stop when AutoSource has enough articles. Heuristic scrapers are separate tiers so SemanticHtml can satisfy before Html runs.
[ [Schema, Microdata, Microformats2, JsonState, XhrArticles].freeze, [WordpressApi, Sitemap, MetaOembed].freeze, [SemanticHtml].freeze, [Html].freeze ].freeze
- SCRAPERS =
Flat ordered list (request slot accounting, detection helpers).
SCRAPER_TIERS.flatten.freeze
- HEURISTIC_SCRAPERS =
Heuristic scrapers that share one memoized SST::Document per page.
[SemanticHtml, Html].freeze
- REQUEST_SESSION_SCRAPERS =
Scrapers that accept a shared follow-up
request_session. [WordpressApi, Sitemap, MetaOembed].freeze
- CAPTURED_RESPONSE_SCRAPERS =
Scrapers that consume browser-captured XHR/fetch JSON bodies.
[XhrArticles].freeze
Class Method Summary collapse
-
.build_instance(scraper, parsed_body, opts:, url:, request_session: nil, body: nil, document: nil, link_resolver: nil, captured_responses: []) ⇒ Object?
Builds a scraper when enabled; returns nil when disabled.
-
.classify_no_scraper_surface(parsed_body, body: nil) ⇒ Symbol
Classifies why scrapers could not extract from a parsed page.
- .extractable_instance?(instance, parsed_body) ⇒ Boolean
-
.from(parsed_body, opts = ) ⇒ Array<Class>
Returns an array of scraper classes that claim to find articles in the parsed body.
- .heuristic_tier?(tier) ⇒ Boolean
- .no_scraper_found_for(parsed_body, body: nil) ⇒ NoScraperFound
- .normalize_sst(parsed_body) ⇒ SST::Document?
Class Method Details
.build_instance(scraper, parsed_body, opts:, url:, request_session: nil, body: nil, document: nil, link_resolver: nil, captured_responses: []) ⇒ Object?
Builds a scraper when enabled; returns nil when disabled.
rubocop:disable Metrics/ParameterLists, Metrics/MethodLength -- construction context for structured and heuristic scrapers
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/html2rss/auto_source/scraper.rb', line 141 def self.build_instance(scraper, parsed_body, opts:, url:, request_session: nil, body: nil, document: nil, link_resolver: nil, captured_responses: []) return unless opts.dig(scraper., :enabled) return if HEURISTIC_SCRAPERS.include?(scraper) && document.nil? scraper_opts = opts.fetch(scraper., {}).except(:enabled) kwargs = construction_kwargs( scraper, request_session:, body:, document:, link_resolver:, captured_responses: ) scraper.new(parsed_body, url:, **kwargs, **scraper_opts) end |
.classify_no_scraper_surface(parsed_body, body: nil) ⇒ Symbol
Classifies why scrapers could not extract from a parsed page.
197 198 199 200 201 202 |
# File 'lib/html2rss/auto_source/scraper.rb', line 197 def self.classify_no_scraper_surface(parsed_body, body: nil) return :blocked_surface if blocked_surface?(parsed_body, body:) return :app_shell if app_shell_surface?(parsed_body) :unsupported_surface end |
.extractable_instance?(instance, parsed_body) ⇒ Boolean
163 164 165 166 167 |
# File 'lib/html2rss/auto_source/scraper.rb', line 163 def self.extractable_instance?(instance, parsed_body) return instance.extractable? if instance.respond_to?(:extractable?) instance.class.articles?(parsed_body) end |
.from(parsed_body, opts = ) ⇒ Array<Class>
Returns an array of scraper classes that claim to find articles in the parsed body.
92 93 94 95 96 97 98 99 |
# File 'lib/html2rss/auto_source/scraper.rb', line 92 def self.from(parsed_body, opts = Html2rss::AutoSource::DEFAULT_CONFIG[:scraper]) scrapers = SCRAPERS.select { |scraper| opts.dig(scraper., :enabled) } scrapers.select! { |scraper| scraper.articles?(parsed_body) } raise no_scraper_found_for(parsed_body) if scrapers.empty? scrapers end |
.heuristic_tier?(tier) ⇒ Boolean
104 105 106 |
# File 'lib/html2rss/auto_source/scraper.rb', line 104 def self.heuristic_tier?(tier) tier.intersect?(HEURISTIC_SCRAPERS) end |
.no_scraper_found_for(parsed_body, body: nil) ⇒ NoScraperFound
173 174 175 |
# File 'lib/html2rss/auto_source/scraper.rb', line 173 def self.no_scraper_found_for(parsed_body, body: nil) NoScraperFound.new(category: classify_no_scraper_surface(parsed_body, body:)) end |
.normalize_sst(parsed_body) ⇒ SST::Document?
111 112 113 114 115 |
# File 'lib/html2rss/auto_source/scraper.rb', line 111 def self.normalize_sst(parsed_body) SST::Normalizer.call(parsed_body) rescue ArgumentError nil end |