FastFeedParser

repository·main·Indexed 41 days ago

https://github.com/kagisearch/fastfeedparser

A high-performance Python library for parsing RSS 2.0, Atom 1.0, and RDF/RSS 1.0 feeds. Designed to be significantly faster than the standard feedparser library by utilizing lxml and efficient memory management, it provides a FastFeedParserDict object for easy access to feed metadata and entries. It supports optional Brotli and dateparser extensions, handles various date formats via ISO-8601 UTC standardization, and allows configurable extraction of content, tags, media, and enclosures.

Tokens
2.9K
Snippets
9
Records
13
Agent score
51%

What's inside FastFeedParser

  1. Access feed metadata and entries in the `FastFeedParserDict`

    main

    The parser returns a FastFeedParserDict object containing two main sections: feed (global metadata) and entries (a list of individual items).

    Accessing Global Feed Information

    Use the .feed attribute to access metadata like title, link, and description:

    print(myfeed.feed.title)
    print(myfeed.feed.link)

    Accessing Entry Information

    Iterate through .entries to access item-specific data. Common fields include:

    • title: Entry title
    • link: Entry URL
    • description: Entry description/summary
    • published: Publication date (standardized to UTC ISO 8601)
    • author: Author information
    • content: Full content
    • media_content: Media attachments
    • enclosures: Attached files
    import fastfeedparser
    
    myfeed = fastfeedparser.parse('https://example.com/feed.xml')
    
    # Access feed global information
    print(myfeed.feed.title)
    print(myfeed.feed.link)
    
    # Access feed entries
    for entry in myfeed.entries:
        print(entry.title)
        print(entry.link)
        print(entry.published)
  2. Install FastFeedParser

    main

    Install the core package using pip:

    pip install fastfeedparser

    Optional Extras

    Depending on your needs, you can install additional dependencies:

    • Brotli support (for Content-Encoding: br):
      pip install fastfeedparser[brotli]
    - **Advanced date parsing fallback** (using `dateparser`):
      ```bash
    pip install fastfeedparser[dateparser]
    • Full installation (includes both Brotli and dateparser):
      pip install fastfeedparser[full]
  3. Access parsed feed data with FastFeedParserDict

    main

    The parse function returns a FastFeedParserDict. This is a specialized dictionary that allows you to access keys as attributes, making it behave similarly to an object. This is useful for navigating nested feed structures like feed.title or entry.link instead of using bracket notation feed['title'].

    from fastfeedparser import parse
    
    feed = parse("https://example.com/feed.xml")
    
    # Accessing feed-level information as attributes
    print(feed.feed.title)
    print(feed.feed.link)
    
    # Accessing entries
    for entry in feed.entries:
        print(entry.title)
        print(entry.link)
  4. Parse a feed from a URL or string using `parse()`

    main

    The fastfeedparser.parse() function is the primary entry point. It accepts a URL or a raw XML/JSON string as the source argument.

    Usage Examples

    Parsing from a URL:

    import fastfeedparser
    myfeed = fastfeedparser.parse('https://example.com/feed.xml')

    Parsing from a string:

    import fastfeedparser
    xml_content = '''<?xml version="1.0"?>
    <rss version="2.0">
        <channel>
            <title>Example Feed</title>
        </channel>
    </rss>'''
    myfeed = fastfeedparser.parse(xml_content)
    import fastfeedparser
    
    # Parse from URL
    myfeed = fastfeedparser.parse('https://example.com/feed.xml')
    
    # Parse from string
    xml_content = '''<?xml version="1.0"?>
    <rss version="2.0">
        <channel>
            <title>Example Feed</title>
            ...
        </channel>
    </rss>'''
    myfeed = fastfeedparser.parse(xml_content)
  5. Configure field extraction in `parse()`

    main

    The parse() function allows you to toggle specific field extractions to optimize parsing speed. Use these keyword arguments:

    • include_content (bool): Whether to extract full content.
    • include_tags (bool): Whether to extract tags.
    • include_media (bool): Whether to extract media information.
    • include_enclosures (bool): Whether to extract enclosures.

    All arguments default to True to ensure complete parsing.

    # Example of optimized parsing by disabling heavy fields
    myfeed = fastfeedparser.parse('https://example.com/feed.xml', include_content=False, include_media=False)
  6. Run the FastFeedParser benchmark

    main

    To compare the performance of FastFeedParser against the standard feedparser library, run the included benchmark script:

    python benchmark.py

    The output will show the speedup factor for various feeds and a summary report including total wall-clock time, average parsing time per feed, and feeds processed per second.

  7. Normalize ISO-8601 datetime strings with `_normalize_iso_datetime_string`

    main

    The _normalize_iso_datetime_string function coerces flexible ISO-8601 inputs into a format compatible with Python's datetime.fromisoformat.

    It performs several specific transformations:

    • Converts Z or z suffixes to +00:00.
    • Handles timezone offsets like +HH:MM or -HH:MM.
    • Replaces common timezone suffixes like UTC, GMT, or Z with +00:00.
    • Converts space-separated date/time (e.g., 2024-01-15 10:30:00) to the T separator format (2024-01-15T10:30:00).
    • Fixes missing colons in timezone offsets (e.g., +0500 to +05:00).
    • Normalizes sub-second fractions to a maximum of 6 digits.
    # Example transformations:
    # "2024-01-15T10:30:00Z" -> "2024-01-15T10:30:00+00:00"
    # "2024-01-15 10:30:00" -> "2024-01-15T10:30:00"
    # "2024-01-15T10:30:00 GMT" -> "2024-01-15T10:30:00+00:00"
  8. Handle entry content and descriptions

    main

    FastFeedParser provides mechanisms to extract the main body content of a feed entry.

    Content Extraction

    When include_content is enabled, the parser looks for:

    • RSS: <content:encoded> or <content> elements, falling back to the <description> text.
    • Atom: The <content> element.

    Content is returned as a list of dictionaries containing type (e.g., text/html, application/xhtml+xml), language, base, and the value (the actual content string).

    Description Synthesis

    If an entry has content but lacks a description, the parser can synthesize a description by:

    1. Stripping HTML tags from the beginning of the content (up to 2048 characters).
    2. Unescaping HTML entities.
    3. Collapsing whitespace.
    4. Truncating the result to 512 characters.
  9. Parse date strings to ISO-8601 UTC format with `_parse_date`

    main

    The _parse_date function is a high-performance utility designed to convert various date string formats (common in RSS and Atom feeds) into a standardized ISO-8601 formatted UTC string.

    It employs a multi-tiered strategy for speed and reliability:

    1. Fast Path (ISO-8601): Attempts to directly parse common ISO-8601 formats (e.g., ending in Z or +HH:MM) using datetime.fromisoformat.
    2. Normalization: Handles common errors like invalid leap years (e.g., converting 2023-02-29 to 2023-02-28) and invalid 24:00 hour representations.
    3. RFC-822 Fast Path: Uses a specialized regex-based parser for RFC-822/2822 dates to bypass heavy datetime object creation where possible.
    4. Fallback Parsers: If fast paths fail, it falls back to dateutil.parser and optionally the dateparser library (if installed) to handle highly irregular formats.

    Returns: An ISO-8601 formatted UTC string (e.g., 2024-01-15T10:30:00+00:00) or None if parsing fails.

    # Example usage (assuming _parse_date is available in your context)
    iso_date = _parse_date("2024-01-15T10:30:00Z")
    # Returns: "2024-01-15T10:30:00+00:00"
    
    iso_date_rfc = _parse_date("Mon, 15 Jan 2024 10:30:00 GMT")
    # Returns: "2024-01-15T10:30:00+00:00"
  10. Extract tags and categories from feeds

    main

    The parser supports extracting taxonomies (tags or categories) from RSS, Atom, and RDF feeds when include_tags is set to True.

    • RSS: Extracts <category> elements and <dc:subject> elements. The term is the text content, and scheme is mapped from the domain attribute.
    • Atom: Extracts <category> elements. Each tag includes term, scheme, and label attributes.
    • RDF: Extracts <dc:subject> elements and <taxo:topic> elements. For taxo:topic, the term is derived from the element text or the rdf:resource attribute.
  11. Parse a feed using parse()

    main

    The parse function is the primary entry point for the library. It can accept either a URL string (starting with http:// or https://) or raw XML/JSON content as a string or bytes. It automatically handles fetching content from URLs, managing redirects (including HTML meta-refresh redirects), and detecting the feed format (RSS, Atom, RDF, or JSON Feed).

    Arguments

    • source (str | bytes): A URL string or the raw XML/JSON content.
    • include_content (bool, default True): If true, includes per-entry content blobs and synthesized descriptions.
    • include_tags (bool, default True): If true, includes feed and entry tags/categories.
    • include_media (bool, default True): If true, includes media namespace content (e.g., media:content, media:thumbnail).
    • include_enclosures (bool, default True): If true, includes RSS enclosures and JSON-feed attachments.

    Returns

    A FastFeedParserDict containing the parsed feed data.

    Raises

    • ValueError: If the content is empty, invalid, or if the response body exceeds the size limit.
    • HTTPError: If the URL fetch fails.
    from fastfeedparser import parse
    
    # Parse from a URL
    feed = parse("https://example.com/feed.xml")
    
    # Parse from raw XML string
    xml_data = "<rss>...</rss>"
    feed = parse(xml_data)
    
    # Parse with specific options
    feed = parse(
        "https://example.com/feed.xml",
        include_content=False,
        include_tags=True
    )
  12. Parse media content and enclosures from feed entries

    main

    FastFeedParser can extract rich media information and file attachments (enclosures) from feed entries.

    Media Content

    If include_media is enabled, the parser extracts metadata for media elements, including:

    • url: The media URL
    • type: MIME type
    • medium: The medium type (e.g., image, video)
    • width / height: Dimensions (coerced to integers)
    • title / text / description: Textual metadata
    • credit / credit_scheme: Attribution information
    • thumbnail_url: URL for a thumbnail

    Enclosures

    If include_enclosures is enabled, the parser extracts file attachments. Each enclosure contains:

    • url: The file URL
    • type: The MIME type
    • length: The file size in bytes (coerced to an integer)

    Note: These features depend on the presence of the appropriate namespaces (like media) in the feed.