rssfeed


Namerssfeed JSON
Version 0.4.1 PyPI version JSON
download
home_pageNone
SummaryA simple rss/atom feed parser
upload_time2025-02-18 11:55:08
maintainerNone
docs_urlNone
authorp7e4
requires_python>=3.12
licenseGPLv3
keywords rssfeed rss feed atom opml
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # rssfeed

A simple rss/atom/opml parser

## Installation

`pip install rssfeed`


## Get Started

### rss parse

``` python
import requests
import rssfeed

text = requests.get("https://lobste.rs/rss").text
rssfeed.parse(text)
```

``` json
{
    "name": "Lobsters",
    "lastupdate": 1739824193,
    "items": [
        {
            "title": "Why I'm Writing a Scheme Implementation in 2025 (The Answer is Async Rust)",
            "author": "maplant.com by mplant",
            "timestamp": 1739824193,
            "url": "https://maplant.com/2025-02-17-Why-I'm-Writing-a-Scheme-Implementation-in-2025-(The-Answer-is-Async-Rust).html",
            "content": "<p><a href=\"https://lobste.rs/s/zm1g8r/why_i_m_writing_scheme_implementation\">Comments</a></p>"
        },
        {
            "title": "14 years of systemd",
            "author": "lwn.net via calvin",
            "timestamp": 1739814564,
            "url": "https://lwn.net/SubscriberLink/1008721/7c31808d76480012/",
            "content": "<p><a href=\"https://lobste.rs/s/c6rk0l/14_years_systemd\">Comments</a></p>"
        },
        {
            "title": "Making the Web More Readable With Stylus",
            "author": "wezm.net by wezm",
            "timestamp": 1739757928,
            "url": "https://www.wezm.net/v2/posts/2025/stylus/",
            "content": "<p><a href=\"https://lobste.rs/s/sag0p3/making_web_more_readable_with_stylus\">Comments</a></p>"
        }
    ]
}
```

> rssfeed **does not** escape HTML tag, which mean if you does not check the content and display it somewhere html can be rendered, it may lead to [Cross-site scripting](https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting) attacks.


### opml parse

``` python
import rssfeed
opml = """
<?xml version="1.0" encoding="UTF-8"?>
<opml version="1.0">
  <head>
    <title>demo feeds</title>
  </head>
  <body>
    <outline text="news">
      <outline text="奇客Solidot" xmlUrl="https://www.solidot.org/index.rss" type="rss" />
      <outline text="news-submenu">
        <outline text="Lobsters" xmlUrl="https://lobste.rs/rss" type="rss" />
      </outline>
    </outline>
    <outline text="阮一峰的网络日志" xmlUrl="https://feeds.feedburner.com/ruanyifeng" type="rss" />
  </body>
</opml>
"""
rssfeed.opmlParse(opml)
````

``` json
{
    "default": [
        {
            "name": "阮一峰的网络日志",
            "url": "https://feeds.feedburner.com/ruanyifeng"
        }
    ],
    "news": [
        {
            "name": "奇客Solidot",
            "url": "https://www.solidot.org/index.rss"
        },
        {
            "name": "Lobsters",
            "url": "https://lobste.rs/rss"
        }
    ]
}
```

as you can see, a two-layer structure will always be generated regardless of the original structure. If the original file includes multiple levels, only the outermost menu is retained. If a feed on the root it will be place in `default` menu.


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "rssfeed",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": null,
    "keywords": "rssfeed, rss, feed, atom, opml",
    "author": "p7e4",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/49/e5/8b66813793fcd4d04f25edd09cd8c6ac303138c221cb154bbf6514540015/rssfeed-0.4.1.tar.gz",
    "platform": null,
    "description": "# rssfeed\n\nA simple rss/atom/opml parser\n\n## Installation\n\n`pip install rssfeed`\n\n\n## Get Started\n\n### rss parse\n\n``` python\nimport requests\nimport rssfeed\n\ntext = requests.get(\"https://lobste.rs/rss\").text\nrssfeed.parse(text)\n```\n\n``` json\n{\n    \"name\": \"Lobsters\",\n    \"lastupdate\": 1739824193,\n    \"items\": [\n        {\n            \"title\": \"Why I'm Writing a Scheme Implementation in 2025 (The Answer is Async Rust)\",\n            \"author\": \"maplant.com by mplant\",\n            \"timestamp\": 1739824193,\n            \"url\": \"https://maplant.com/2025-02-17-Why-I'm-Writing-a-Scheme-Implementation-in-2025-(The-Answer-is-Async-Rust).html\",\n            \"content\": \"<p><a href=\\\"https://lobste.rs/s/zm1g8r/why_i_m_writing_scheme_implementation\\\">Comments</a></p>\"\n        },\n        {\n            \"title\": \"14 years of systemd\",\n            \"author\": \"lwn.net via calvin\",\n            \"timestamp\": 1739814564,\n            \"url\": \"https://lwn.net/SubscriberLink/1008721/7c31808d76480012/\",\n            \"content\": \"<p><a href=\\\"https://lobste.rs/s/c6rk0l/14_years_systemd\\\">Comments</a></p>\"\n        },\n        {\n            \"title\": \"Making the Web More Readable With Stylus\",\n            \"author\": \"wezm.net by wezm\",\n            \"timestamp\": 1739757928,\n            \"url\": \"https://www.wezm.net/v2/posts/2025/stylus/\",\n            \"content\": \"<p><a href=\\\"https://lobste.rs/s/sag0p3/making_web_more_readable_with_stylus\\\">Comments</a></p>\"\n        }\n    ]\n}\n```\n\n> rssfeed **does not** escape HTML tag, which mean if you does not check the content and display it somewhere html can be rendered, it may lead to [Cross-site scripting](https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting) attacks.\n\n\n### opml parse\n\n``` python\nimport rssfeed\nopml = \"\"\"\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<opml version=\"1.0\">\n  <head>\n    <title>demo feeds</title>\n  </head>\n  <body>\n    <outline text=\"news\">\n      <outline text=\"\u5947\u5ba2Solidot\" xmlUrl=\"https://www.solidot.org/index.rss\" type=\"rss\" />\n      <outline text=\"news-submenu\">\n        <outline text=\"Lobsters\" xmlUrl=\"https://lobste.rs/rss\" type=\"rss\" />\n      </outline>\n    </outline>\n    <outline text=\"\u962e\u4e00\u5cf0\u7684\u7f51\u7edc\u65e5\u5fd7\" xmlUrl=\"https://feeds.feedburner.com/ruanyifeng\" type=\"rss\" />\n  </body>\n</opml>\n\"\"\"\nrssfeed.opmlParse(opml)\n````\n\n``` json\n{\n    \"default\": [\n        {\n            \"name\": \"\u962e\u4e00\u5cf0\u7684\u7f51\u7edc\u65e5\u5fd7\",\n            \"url\": \"https://feeds.feedburner.com/ruanyifeng\"\n        }\n    ],\n    \"news\": [\n        {\n            \"name\": \"\u5947\u5ba2Solidot\",\n            \"url\": \"https://www.solidot.org/index.rss\"\n        },\n        {\n            \"name\": \"Lobsters\",\n            \"url\": \"https://lobste.rs/rss\"\n        }\n    ]\n}\n```\n\nas you can see, a two-layer structure will always be generated regardless of the original structure. If the original file includes multiple levels, only the outermost menu is retained. If a feed on the root it will be place in `default` menu.\n\n",
    "bugtrack_url": null,
    "license": "GPLv3",
    "summary": "A simple rss/atom feed parser",
    "version": "0.4.1",
    "project_urls": {
        "Issues": "https://github.com/p7e4/rssfeed/issues",
        "Repository": "https://github.com/p7e4/rssfeed"
    },
    "split_keywords": [
        "rssfeed",
        " rss",
        " feed",
        " atom",
        " opml"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "83a8f80c4aa998b79651635341f1d64f8c76866faf8840a6e880efc3a6afec34",
                "md5": "86997b09223a105db7d01e4ec6424c2e",
                "sha256": "41717fa6b263660efbde6547fb5efa85f55a7bc8507229024049ccb0f9ce0ab6"
            },
            "downloads": -1,
            "filename": "rssfeed-0.4.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "86997b09223a105db7d01e4ec6424c2e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 16080,
            "upload_time": "2025-02-18T11:55:06",
            "upload_time_iso_8601": "2025-02-18T11:55:06.819835Z",
            "url": "https://files.pythonhosted.org/packages/83/a8/f80c4aa998b79651635341f1d64f8c76866faf8840a6e880efc3a6afec34/rssfeed-0.4.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "49e58b66813793fcd4d04f25edd09cd8c6ac303138c221cb154bbf6514540015",
                "md5": "15e820801340556621730077bfd6a316",
                "sha256": "37d4621fd04186c8221883f6aec197260f5e9d6dbfdc5ad62ea90f61606778e6"
            },
            "downloads": -1,
            "filename": "rssfeed-0.4.1.tar.gz",
            "has_sig": false,
            "md5_digest": "15e820801340556621730077bfd6a316",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 15327,
            "upload_time": "2025-02-18T11:55:08",
            "upload_time_iso_8601": "2025-02-18T11:55:08.423906Z",
            "url": "https://files.pythonhosted.org/packages/49/e5/8b66813793fcd4d04f25edd09cd8c6ac303138c221cb154bbf6514540015/rssfeed-0.4.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-02-18 11:55:08",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "p7e4",
    "github_project": "rssfeed",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "rssfeed"
}
        
Elapsed time: 0.84416s