Class: Html2rss::Selectors
- Inherits:
-
Object
- Object
- Html2rss::Selectors
- Includes:
- Enumerable
- Defined in:
- lib/html2rss/selectors.rb,
lib/html2rss/selectors/extractors.rb,
lib/html2rss/selectors/item_scope.rb,
lib/html2rss/selectors/extractors/href.rb,
lib/html2rss/selectors/extractors/html.rb,
lib/html2rss/selectors/extractors/text.rb,
lib/html2rss/selectors/post_processors.rb,
lib/html2rss/selectors/extractors/static.rb,
lib/html2rss/selectors/extractors/attribute.rb,
lib/html2rss/selectors/post_processors/base.rb,
lib/html2rss/selectors/post_processors/gsub.rb,
lib/html2rss/selectors/object_to_xml_converter.rb,
lib/html2rss/selectors/post_processors/template.rb,
lib/html2rss/selectors/post_processors/parse_uri.rb,
lib/html2rss/selectors/post_processors/substring.rb,
lib/html2rss/selectors/post_processors/parse_time.rb,
lib/html2rss/selectors/post_processors/sanitize_html.rb,
lib/html2rss/selectors/post_processors/html_to_markdown.rb,
lib/html2rss/selectors/post_processors/markdown_to_html.rb,
lib/html2rss/selectors/post_processors/html_transformers/wrap_img_in_a.rb,
lib/html2rss/selectors/post_processors/html_transformers/transform_urls_to_absolute_ones.rb
Overview
This scraper is designed to scrape articles from a given HTML page using CSS selectors defined in the feed config.
It supports the traditional feed configs that html2rss originally provided, ensuring compatibility with existing setups.
Additionally, it uniquely offers the capability to convert JSON into XML, extending its versatility for diverse data processing workflows.
Defined Under Namespace
Modules: Extractors, PostProcessors Classes: Context, InvalidSelectorName, ItemScope, ObjectToXmlConverter
Constant Summary collapse
- DEFAULT_CONFIG =
Default selectors options merged into user configuration.
{ items: { enhance: true } }.freeze
- ITEMS_SELECTOR_KEY =
Selector key that points to the root list of article nodes.
:items- ITEM_TAGS =
Supported RSS item attributes extractable through selectors.
%i[title url description author comments published_at guid enclosure categories].freeze
- SPECIAL_ATTRIBUTES =
Item attributes that require dedicated extraction logic.
Set[:guid, :enclosure, :categories].freeze
- SELECTOR_TO_ARTICLE_KEY =
Config selector keys that map onto a different Article attribute.
:enclosurestays singular in YAML; Article stores:enclosures. { enclosure: :enclosures }.freeze
- SELECTABLE_SELECTOR_KEYS =
Selector keys that may be copied onto an Article (PROVIDED_KEYS + mapped aliases).
(Html2rss::Article::PROVIDED_KEYS + SELECTOR_TO_ARTICLE_KEY.keys).to_set.freeze
Instance Method Summary collapse
-
#articles ⇒ Array<Html2rss::Article>
Returns articles extracted from the response.
-
#each {|article| ... } ⇒ Enumerator
Iterates over each scraped article.
-
#enhance? ⇒ Boolean
Whether to enhance the article hash with auto_source's semantic HTML extraction.
-
#enhance_article_hash(article_hash, article_tag, base_url = @url) ⇒ Hash
Enhances the article hash using semantic HTML extraction.
-
#extract_article(item, page_response = response) ⇒ Hash
Extracts an article hash for a given item element.
-
#initialize(response, selectors:, time_zone:) ⇒ Selectors
constructor
Initializes a new Selectors instance.
-
#items_selector ⇒ String
Returns the CSS selector for the items.
-
#select(name, item, base_url: @url) ⇒ Object+
Selects the value for a given attribute from an HTML element.
-
#select_in_scope(name, scope) ⇒ Object+
Selects the value for a given attribute within an existing ItemScope.
Constructor Details
#initialize(response, selectors:, time_zone:) ⇒ Selectors
Initializes a new Selectors instance.
46 47 48 49 50 51 52 53 54 |
# File 'lib/html2rss/selectors.rb', line 46 def initialize(response, selectors:, time_zone:) @response = response @url = response.url @selectors = selectors @time_zone = time_zone prepare_selectors! @rss_item_attributes = @selectors.keys.select { |key| SELECTABLE_SELECTOR_KEYS.include?(key) } end |
Instance Method Details
#articles ⇒ Array<Html2rss::Article>
Returns articles extracted from the response. Reverses order if config specifies reverse ordering.
61 62 63 |
# File 'lib/html2rss/selectors.rb', line 61 def articles @articles ||= @selectors.dig(ITEMS_SELECTOR_KEY, :order) == 'reverse' ? to_a.tap(&:reverse!) : to_a end |
#each {|article| ... } ⇒ Enumerator
Iterates over each scraped article.
70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/html2rss/selectors.rb', line 70 def each(&) return enum_for(:each) unless block_given? enhance = enhance? parsed_body.css(items_selector).each do |item| article_hash = extract_article(item, response) enhance_article_hash(article_hash, item, response.url) if enhance yield Html2rss::Article.new(**article_hash, scraper: self.class) end end |
#enhance? ⇒ Boolean
Returns whether to enhance the article hash with auto_source's semantic HTML extraction.
90 |
# File 'lib/html2rss/selectors.rb', line 90 def enhance? = !!@selectors.dig(ITEMS_SELECTOR_KEY, :enhance) |
#enhance_article_hash(article_hash, article_tag, base_url = @url) ⇒ Hash
Enhances the article hash using semantic HTML extraction. Only adds keys that are missing from the original hash.
rubocop:disable Metrics/MethodLength
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/html2rss/selectors.rb', line 118 def enhance_article_hash(article_hash, article_tag, base_url = @url) selected_anchor = Html2rss::Html::Navigator.main_anchor_for(article_tag) extracted = Html2rss::Html::ArticleExtractor.call( article_tag, base_url:, selected_anchor:, fallback_anchorless: true ) return article_hash unless extracted extracted.each_with_object(article_hash) do |(key, value), hash| next if value.nil? || (hash.key?(key) && hash[key]) hash[key] = value end end |
#extract_article(item, page_response = response) ⇒ Hash
Extracts an article hash for a given item element.
98 99 100 101 102 103 104 105 106 107 |
# File 'lib/html2rss/selectors.rb', line 98 def extract_article(item, page_response = response) scope = item_scope_for(item, page_response.url) @rss_item_attributes.each_with_object({}) do |selector_key, hash| value = scope.select(selector_key) next if value.nil? article_key = SELECTOR_TO_ARTICLE_KEY.fetch(selector_key, selector_key) hash[article_key] = article_key == :enclosures ? wrap_enclosure_value(value) : value end end |
#items_selector ⇒ String
Returns the CSS selector for the items.
87 |
# File 'lib/html2rss/selectors.rb', line 87 def items_selector = @selectors.dig(ITEMS_SELECTOR_KEY, :selector) |
#select(name, item, base_url: @url) ⇒ Object+
Selects the value for a given attribute from an HTML element.
144 145 146 |
# File 'lib/html2rss/selectors.rb', line 144 def select(name, item, base_url: @url) select_in_scope(name, item_scope_for(item, base_url)) end |
#select_in_scope(name, scope) ⇒ Object+
Selects the value for a given attribute within an existing ItemScope. Used by Html2rss::Selectors::ItemScope#select so nested selects reuse one scope per extraction pass.
156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/html2rss/selectors.rb', line 156 def select_in_scope(name, scope) name = name.to_sym raise InvalidSelectorName, "Attribute selector '#{name}' is reserved for items." if name == ITEMS_SELECTOR_KEY selector_key, config = selector_config_for(name) if SPECIAL_ATTRIBUTES.member?(selector_key) select_special(selector_key, scope:, config:) else select_regular(selector_key, scope:, config:) end end |