### Feed image example in XML and HTML Source: https://feedparser.readthedocs.io/en/latest/reference-feed-image The first block shows a feed image in RSS/XML format, and the second shows the equivalent HTML rendering. The XML example includes the image title, URL, link, width, height, and description. The HTML example wraps the image in an anchor and uses the same values for the src, width, height, alt, and title attributes. ```xml Feed logo http://example.org/logo.png http://example.org/ 80 15 Visit my home page ``` ```html Feed logo ``` -------------------------------- ### Atom 0.3 feed example Source: https://feedparser.readthedocs.io/en/latest/annotated-atom03 A complete Atom 0.3 feed example showing required and optional elements such as title, tagline, link, copyright, generator, id, modified, info, entry, author, contributor, summary, and content. Use this as a reference for parsing Atom 0.3 feeds with feedparser. Note that real-world feeds may omit any element, so parsed results may not contain all fields. ```xml Sample Feed For documentation <em>only</em> <p>Copyright 2004, Mark Pilgrim</p>< Sample Toolkit tag:feedparser.org,2004-04-20:/docs/examples/atom03.xml 2004-04-20T11:56:34Z

This is an Atom syndication feed.

First entry title tag:feedparser.org,2004-04-20:/docs/examples/atom03.xml:3 2004-04-19T07:45:00Z 2004-04-20T00:23:47Z 2004-04-20T11:56:34Z Mark Pilgrim http://diveintomark.org/ mark@example.org Joe http://example.org/joe/ joe@example.org Sam http://example.org/sam/ sam@example.org Watch out for nasty tricks
Watch out for nasty tricks
``` -------------------------------- ### Testing for element existence with Python dictionary idioms Source: https://feedparser.readthedocs.io/en/latest/basic-existence Use standard Python dictionary idioms to test for the presence of feed elements before accessing their values. The example checks membership with 'in' and uses the get() method with default values to handle missing elements safely. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom10.xml') >>> 'title' in d.feed True >>> 'ttl' in d.feed False >>> d.feed.get('title', 'No title') 'Sample feed' >>> d.feed.get('ttl', 60) 60 ``` -------------------------------- ### Parse a feed from a local file with feedparser.parse Source: https://feedparser.readthedocs.io/en/latest/introduction Use this snippet to parse a feed from a local file. The example assumes Windows and a file saved at c:\incoming\atom10.xml; use the path syntax appropriate for your platform. ```python >>> import feedparser >>> d = feedparser.parse(r'c:\incoming\atom10.xml') >>> d['feed']['title'] 'Sample Feed' ``` -------------------------------- ### Accessing multiple links in an Atom entry Source: https://feedparser.readthedocs.io/en/latest/uncommon-atom Shows how to access the list of links for an Atom entry. The example parses an Atom feed and retrieves the first entry's links, demonstrating that each link is a dictionary with 'rel', 'type', 'href', and optionally 'length' keys. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom10.xml') >>> e = d.entries[0] >>> len(e.links) 4 >>> e.links[0] {'rel': 'alternate', 'type': 'text/html', 'href': 'http://example.org/entry/3'} >>> e.links[1] {'rel': 'related', 'type': 'text/html', 'href': 'http://search.example.com/'} >>> e.links[2] {'rel': 'via', 'type': 'text/html', 'href': 'http://toby.example.com/examples/atom10'} >>> e.links[3] {'rel': 'enclosure', 'type': 'video/mpeg4', 'href': 'http://www.example.com/movie.mp4', 'length': '42301'} ``` -------------------------------- ### Sample RSS 2.0 feed Source: https://feedparser.readthedocs.io/en/latest/annotated-rss20 A complete RSS 2.0 feed example with channel and item elements. Note that real-world feeds may omit any element, so parsed results may not include all fields. ```xml Sample Feed For documentation <em>only</em> http://example.org/ en Copyright 2004, Mark Pilgrim editor@example.org webmaster@example.org Sat, 07 Sep 2002 0:00:01 GMT Examples Sample Toolkit http://feedvalidator.org/docs/rss2.html 60 http://example.org/banner.png Example banner http://example.org/ 80 15 Search Search this site: q http://example.org/mt/mt-search.cgi First item title http://example.org/item/1 Watch out for <span style="background: url(javascript:window.location='http://example.org/')"> nasty tricks</span> mark@example.org Miscellaneous http://example.org/comments/1 http://example.org/guid/1 Thu, 05 Sep 2002 0:00:01 GMT ``` -------------------------------- ### Basic authentication via URL credentials Source: https://feedparser.readthedocs.io/en/latest/http-authentication Embeds the username and password in the feed URL to access a basic-authentication-protected feed. The example uses username 'test' and password 'basic'. ```python >>> import feedparser >>> d = feedparser.parse('http://test:basic@feedparser.org/docs/examples/basic_auth.xml') >>> d.feed.title 'Sample Feed' ``` -------------------------------- ### Accessing contributors in an Atom feed Source: https://feedparser.readthedocs.io/en/latest/uncommon-atom Shows how to access the list of contributors for an Atom entry. The example parses an Atom feed and retrieves the first entry's contributors, demonstrating that each contributor is a dictionary with 'name', 'href', and 'email' keys. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom10.xml') >>> e = d.entries[0] >>> len(e.contributors) 2 >>> e.contributors[0] {'name': 'Joe', 'href': 'http://example.org/joe/', 'email': 'joe@example.org'} >>> e.contributors[1] {'name': 'Sam', 'href': 'http://example.org/sam/', 'email': 'sam@example.org'} ``` -------------------------------- ### Content-Location HTTP header Source: https://feedparser.readthedocs.io/en/latest/resolving-relative-links Demonstrates that when no root-level xml:base is specified, the default base URI is given by the Content-Location HTTP header. The example parses a feed with http_base.xml and shows resolved links. ```python >>> import feedparser >>> d = feedparser.parse("https://feedparser.readthedocs.io/en/latest/examples/http_base.xml") >>> d.feed.link 'http://example.org/index.html' >>> d.entries[0].link 'http://example.org/archives/000001.html' ``` -------------------------------- ### Annotated RSS 2.0 feed with namespaces Source: https://feedparser.readthedocs.io/en/latest/annotated-rss20-dc A complete RSS 2.0 feed example using the dc, admin, content, and rdf namespaces. It includes channel metadata and one item with content:encoded. Note that real-world feeds may omit any element, so do not rely on any particular element being present in parsed results. ```XML Sample Feed http://example.org/ For documentation only en-us Mark Pilgrim (mark@example.org) Copyright 2004 Mark Pilgrim 2004-06-04T17:40:33-05:00 First of all http://example.org/archives/2002/09/04.html#first_of_all 1983@example.org Americans are fat. Smokers are stupid. People who don’t speak Perl are irrelevant. Quotes 2002-09-04T13:54:20-05:00 Ian Hickson: Americans are fat. Smokers are stupid. People who don’t speak Perl are irrelevant. ]]> ``` -------------------------------- ### feed.textinput annotated example: XML feed and HTML rendering Source: https://feedparser.readthedocs.io/en/latest/reference-feed-textinput The first block shows a feed's text input element with title, link, name, and description. The second block shows how that text input could be rendered as an HTML form, mapping the feed fields to form attributes and labels. ```xml Go! http://example.org/search keyword Search this site: ``` ```html
``` -------------------------------- ### Accessing feed version with feedparser.parse Source: https://feedparser.readthedocs.io/en/latest/version-detection Use the version attribute of the parsed feed object to get the detected feed type and version. The examples show parsing various feed URLs and the corresponding version strings returned. ```python >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom10.xml') >>> d.version 'atom10' >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom03.xml') >>> d.version 'atom03' >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/rss20.xml') >>> d.version 'rss20' >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/rss20dc.xml') >>> d.version 'rss20' >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/rss10.rdf') >>> d.version 'rss10' ``` -------------------------------- ### Send custom HTTP request headers with feedparser.parse Source: https://feedparser.readthedocs.io/en/latest/http-other Pass a dictionary of request headers to the request_headers parameter of feedparser.parse. The example sets Cache-control to max-age=0. ```python import feedparser d = feedparser.parse( 'https://feedparser.readthedocs.io/en/latest/examples/atom03.xml', request_headers={'Cache-control': 'max-age=0'}, ) ``` -------------------------------- ### Access HTTP response headers via d.headers Source: https://feedparser.readthedocs.io/en/latest/http-other After parsing a feed, the d.headers dictionary contains the HTTP response headers. The example shows the output for a sample feed, including date, server, etag, and content-type. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom03.xml') >>> d.headers {'date': 'Fri, 11 Jun 2004 23:57:50 GMT', 'server': 'Apache/2.0.49 (Debian GNU/Linux)', 'last-modified': 'Fri, 11 Jun 2004 23:00:34 GMT', 'etag': '"6c132-941-ad7e3080"', 'accept-ranges': 'bytes', 'vary': 'Accept-Encoding,User-Agent', 'content-encoding': 'gzip', 'content-length': '883', 'connection': 'close', 'content-type': 'application/xml'} ``` -------------------------------- ### Overriding xml:base on an Source: https://feedparser.readthedocs.io/en/latest/resolving-relative-links Demonstrates that an xml:base attribute on an overrides the xml:base on the parent . The example accesses entry link and author_detail.href, which resolve to the entry's base URI. ```python >>> import feedparser >>> d = feedparser.parse("https://feedparser.readthedocs.io/en/latest/examples/base.xml") >>> d.entries[0].link 'http://example.org/archives/000001.html' >>> d.entries[0].author_detail.href 'http://example.org/about/' ``` -------------------------------- ### Atom 1.0 XML Feed Structure Source: https://feedparser.readthedocs.io/en/latest/annotated-atom10 A complete example of an Atom 1.0 feed containing metadata, entry details, authors, contributors, and content. This structure serves as a reference for how feedparser maps XML elements. ```xml Sample Feed For documentation <em>only</em> <p>Copyright 2005, Mark Pilgrim</p> Sample Toolkit tag:feedparser.org,2005-11-09:/docs/examples/atom10.xml 2005-11-09T11:56:34Z First entry title tag:feedparser.org,2005-11-09:/docs/examples/atom10.xml:3 2005-11-09T00:23:47Z 2005-11-09T11:56:34Z Mark Pilgrim http://diveintomark.org/ mark@example.org Joe http://example.org/joe/ joe@example.org Sam http://example.org/sam/ sam@example.org Watch out for nasty tricks
Watch out for nasty tricks
``` -------------------------------- ### xml:base on root-level element Source: https://feedparser.readthedocs.io/en/latest/resolving-relative-links Shows that an xml:base on the root element sets the base URI for all URIs in the feed. The example parses a feed and accesses feed.link and feed.generator_detail.href, which resolve to the base URI. ```python >>> import feedparser >>> d = feedparser.parse("https://feedparser.readthedocs.io/en/latest/examples/base.xml") >>> d.feed.link 'http://example.org/index.html' >>> d.feed.generator_detail.href 'http://example.org/generator/' ``` -------------------------------- ### Feed URL as default base URI Source: https://feedparser.readthedocs.io/en/latest/resolving-relative-links Shows that when no root-level xml:base and no Content-Location header are present, the feed's own URL is the default base URI. The example parses no_base.xml and shows resolved links. ```python >>> import feedparser >>> d = feedparser.parse("https://feedparser.readthedocs.io/en/latest/examples/no_base.xml") >>> d.feed.link 'http://feedparser.org/docs/examples/index.html >>> d.entries[0].link 'http://example.org/archives/000001.html' ``` -------------------------------- ### Digest authentication via URL credentials Source: https://feedparser.readthedocs.io/en/latest/http-authentication Embeds the username and password in the feed URL to access a digest-authentication-protected feed. The example uses username 'test' and password 'digest'. Note that this technique sends the password in an easily decryptable form. ```python >>> import feedparser >>> d = feedparser.parse('http://test:digest@feedparser.org/docs/examples/digest_auth.xml') >>> d.feed.title 'Sample Feed' ``` -------------------------------- ### Relative links within embedded HTML Source: https://feedparser.readthedocs.io/en/latest/resolving-relative-links Shows that an xml:base on overrides the parent 's base, and that the base URI for the element is used for embedded HTML/XHTML markup. The example accesses the content value, which contains resolved links. ```python >>> import feedparser >>> d = feedparser.parse("https://feedparser.readthedocs.io/en/latest/examples/base.xml") >>> d.entries[0].content[0].value '

skip to anchor 2

Some content

This is anchor 2

' ``` -------------------------------- ### Access Atom element details with feedparser Source: https://feedparser.readthedocs.io/en/latest/atom-detail Parses an Atom 1.0 feed and prints the _detail dictionaries for feed title, subtitle, rights, and entry title, summary, and content. The content element is a list, so it is accessed via index. Note: the output for content[0] shows a missing comma after 'language': 'en-US', which is a typo in the original example. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom10.xml') >>> d.feed.title_detail {'type': 'text/plain', 'base': 'http://example.org/', 'language': 'en', 'value': 'Sample Feed'} >>> d.feed.subtitle_detail {'type': 'text/html', 'base': 'http://example.org/', 'language': 'en', 'value': 'For documentation only'} >>> d.feed.rights_detail {'type': 'text/html', 'base': 'http://example.org/', 'language': 'en', 'value': '

Copyright 2004, Mark Pilgrim

'} >>> d.entries[0].title_detail {'type': 'text/plain', 'base': 'http://example.org/', 'language': 'en', 'value': 'First entry title'} >>> d.entries[0].summary_detail {'type': 'text/plain', 'base': 'http://example.org/', 'language': 'en', 'value': 'Watch out for nasty tricks'} >>> len(d.entries[0].content) 1 >>> d.entries[0].content[0] {'type': 'application/xhtml+xml', 'base': 'http://example.org/entry/3', 'language': 'en-US' 'value': '
Watch out for nasty tricks
'} ``` -------------------------------- ### Using ETags to reduce bandwidth Source: https://feedparser.readthedocs.io/en/latest/http-etag Demonstrates how to capture an ETag from an initial request and pass it back in a subsequent request to check for feed updates. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom10.xml') >>> d.etag '"6c132-941-ad7e3080"' >>> d2 = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom10.xml', etag=d.etag) >>> d2.status 304 >>> d2.feed {} >>> d2.entries [] >>> d2.debug_message 'The feed has not changed since you last checked, so the server sent no data. This is a feature, not a bug!' ``` -------------------------------- ### Accessing Common Entry Elements Source: https://feedparser.readthedocs.io/en/latest/common-atom-elements Demonstrates how to access entry-specific elements. Note that content is sanitized and returned as a list of dictionaries. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom10.xml') >>> d.entries[0].title 'First entry title' >>> d.entries[0].link 'http://example.org/entry/3 >>> d.entries[0].id 'tag:feedparser.org,2005-11-09:/docs/examples/atom10.xml:3' >>> d.entries[0].published '2005-11-09T00:23:47Z' >>> d.entries[0].published_parsed (2005, 11, 9, 0, 23, 47, 2, 313, 0) >>> d.entries[0].updated '2005-11-09T11:56:34Z' >>> d.entries[0].updated_parsed (2005, 11, 9, 11, 56, 34, 2, 313, 0) >>> d.entries[0].summary 'Watch out for nasty tricks' >>> d.entries[0].content [{'type': 'application/xhtml+xml', 'base': 'http://example.org/entry/3', 'language': 'en-US', 'value': '
Watch out for nasty tricks
'}] ``` -------------------------------- ### xml:base and sibling attributes Source: https://feedparser.readthedocs.io/en/latest/resolving-relative-links Illustrates that xml:base affects other attributes in the element where it is declared. The example accesses links[1].rel and links[1].href, showing the resolved href. ```python >>> import feedparser >>> d = feedparser.parse("https://feedparser.readthedocs.io/en/latest/examples/base.xml") >>> d.entries[0].links[1].rel 'service.edit' >>> d.entries[0].links[1].href 'http://example.com/api/client/37' ``` -------------------------------- ### Using Last-Modified headers to reduce bandwidth Source: https://feedparser.readthedocs.io/en/latest/http-etag Demonstrates how to capture the Last-Modified date from an initial request and pass it back in a subsequent request to check for feed updates. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom10.xml') >>> d.modified Fri, 11 Jun 2012 23:00:34 GMT >>> d.modified_parsed (2004, 6, 11, 23, 0, 34, 4, 163, 0) >>> d2 = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom10.xml', modified=d.modified) >>> d2.status 304 >>> d2.feed {} >>> d2.entries [] >>> d2.debug_message 'The feed has not changed since you last checked, so the server sent no data. This is a feature, not a bug!' ``` -------------------------------- ### Accessing an Atom feed using RSS terminology Source: https://feedparser.readthedocs.io/en/latest/content-normalization Demonstrates how to parse an Atom feed and access its elements using standard RSS dictionary keys like 'channel' and 'items'. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom10.xml') >>> d['channel']['title'] 'Sample Feed' >>> d['channel']['link'] 'http://example.org/' >>> d['channel']['description'] 'For documentation only >>> len(d['items']) 1 >>> e = d['items'][0] >>> e['title'] 'First entry title' >>> e['link'] 'http://example.org/entry/3' >>> e['description'] 'Watch out for nasty tricks' >>> e['author'] 'Mark Pilgrim (mark@example.org)' ``` -------------------------------- ### Sample Atom Feed XML Source: https://feedparser.readthedocs.io/en/latest/common-atom-elements A sample Atom 1.0 feed structure used for demonstration purposes. ```xml Sample Feed For documentation <em>only</em> <p>Copyright 2005, Mark Pilgrim</p>< tag:feedparser.org,2005-11-09:/docs/examples/atom10.xml Sample Toolkit 2005-11-09T11:56:34Z First entry title tag:feedparser.org,2005-11-09:/docs/examples/atom10.xml:3 2005-11-09T00:23:47Z 2005-11-09T11:56:34Z Watch out for nasty tricks
Watch out for nasty tricks
``` -------------------------------- ### Accessing an RSS feed using Atom terminology Source: https://feedparser.readthedocs.io/en/latest/content-normalization Demonstrates how to parse an RSS feed and access its elements using Atom-style attributes like 'feed.subtitle_detail' and 'entries'. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/rss20.xml') >>> d.feed.subtitle_detail {'type': 'text/html', 'base': 'http://feedparser.org/docs/examples/rss20.xml', 'language': None, 'value': 'For documentation only'} >>> len(d.entries) 1 >>> e = d.entries[0] >>> e.links [{'rel': 'alternate', 'type': 'text/html', 'href': 'http://example.org/item/1'}] >>> e.summary_detail {'type': 'text/html', 'base': 'http://feedparser.org/docs/examples/rss20.xml', 'language': 'en', 'value': 'Watch out for nasty tricks'} >>> e.updated_parsed (2002, 9, 5, 0, 0, 1, 3, 248, 0) ``` -------------------------------- ### Basic authentication with HTTPBasicAuthHandler Source: https://feedparser.readthedocs.io/en/latest/http-authentication Constructs an HTTPBasicAuthHandler with the password information and passes it to the parse function via the handlers parameter. This is the 'hard way' for basic authentication, using the standard urllib2 module. ```python import urllib2, feedparser # Construct the authentication handler auth = urllib2.HTTPBasicAuthHandler() # Add password information: realm, host, user, password. # A single handler can contain passwords for multiple sites; # urllib2 will sort out which passwords get sent to which sites # based on the realm and host of the URL you're retrieving auth.add_password('BasicTest', 'feedparser.org', 'test', 'basic') # Pass the authentication handler to the feed parser. # handlers is a list because there might be more than one # type of handler (urllib2 defines lots of different ones, # and you can build your own) d = feedparser.parse( 'https://feedparser.readthedocs.io/en/latest/examples/basic_auth.xml', handlers=[auth], ) ``` -------------------------------- ### Sample RSS 1.0 Feed Source: https://feedparser.readthedocs.io/en/latest/annotated-rss10 This XML snippet is the annotated RSS 1.0 feed for documentation. It contains the full channel and item elements, including namespaces like rdf, dc, admin, content, and cc. Caution: real feeds may omit required elements, so parsed results may not contain them all. ```xml Sample Feed http://www.example.org/ For documentation only en Mark Pilgrim (mark@example.org) 2004-06-04T17:40:33-05:00 First of all http://example.org/archives/2002/09/04.html#first_of_all Americans are fat. Smokers are stupid. People who don't speak Perl are irrelevant. Quotes 2004-05-30T14:23:54-06:00 Ian Hickson: Americans are fat. Smokers are stupid. People who don't speak Perl are irrelevant. ]]> ``` -------------------------------- ### Customizing the User-Agent header Source: https://feedparser.readthedocs.io/en/latest/http-useragent Use the agent parameter in feedparser.parse to identify your application with a name and URL. ```python >>> import feedparser >>> d = feedparser.parse( ... "https://feedparser.readthedocs.io/en/latest/examples/atom10.xml", ... agent="MyApp/1.0 +http://domain.example/", ... ) ``` -------------------------------- ### HTTP Content-Type header with charset parameter Source: https://feedparser.readthedocs.io/en/latest/character-encoding Shows the HTTP Content-Type header with a charset parameter that specifies the character encoding. If no charset is given, HTTP defaults to iso-8859-1 for text/* media types. ```http Content-Type: text/html; charset="utf-8" ``` -------------------------------- ### Accessing Common Feed Elements Source: https://feedparser.readthedocs.io/en/latest/common-atom-elements Demonstrates how to access top-level feed elements like title, link, and updated dates using feedparser. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/atom10.xml') >>> d.feed.title 'Sample feed' >>> d.feed.link 'http://example.org/' >>> d.feed.subtitle 'For documentation only' >>> d.feed.updated '2005-11-09T11:56:34Z' >>> d.feed.updated_parsed (2005, 11, 9, 11, 56, 34, 2, 313, 0) >>> d.feed.id 'tag:feedparser.org,2005-11-09:/docs/examples/atom10.xml' ``` -------------------------------- ### Noticing permanent redirects with feedparser Source: https://feedparser.readthedocs.io/en/latest/http-redirect Shows how to detect a permanent redirect (HTTP 301) using feedparser. If you receive this status, update your database or configuration with the new URL in d.href to avoid being banned for repeatedly requesting the old address. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/permanent.xml') >>> d.status 301 >>> d.href 'http://feedparser.org/docs/examples/atom10.xml' >>> d.feed.title 'Sample Feed' ``` -------------------------------- ### Noticing feeds marked gone with feedparser Source: https://feedparser.readthedocs.io/en/latest/http-redirect Shows how to detect a feed marked as gone (HTTP 410) using feedparser. If you receive this status, stop polling the feed and inform the user that it is permanently deleted. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/gone.xml') >>> d.status 410 ``` -------------------------------- ### Digest authentication with HTTPDigestAuthHandler Source: https://feedparser.readthedocs.io/en/latest/http-authentication Constructs an HTTPDigestAuthHandler with the necessary realm, host, user, and password information, then passes it to the parse function. This is the secure way for digest authentication because the password is encrypted before being sent. ```python import urllib2, feedparser auth = urllib2.HTTPDigestAuthHandler() auth.add_password('DigestTest', 'feedparser.org', 'test', 'digest') d = feedparser.parse( 'https://feedparser.readthedocs.io/en/latest/examples/digest_auth.xml', handlers=[auth], ) ``` -------------------------------- ### Access feed cloud with feedparser Source: https://feedparser.readthedocs.io/en/latest/uncommon-rss Parses an RSS 2.0 feed and accesses the feed cloud dictionary, which contains domain, port, path, registerprocedure, and protocol. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/rss20.xml') >>> d.feed.cloud {'domain': 'rpc.example.com', 'port': '80', 'path': '/RPC2', 'registerprocedure': 'pingMe', 'protocol': 'soap'} ``` -------------------------------- ### Access enclosures with feedparser Source: https://feedparser.readthedocs.io/en/latest/uncommon-rss Parses an RSS 2.0 feed and accesses the enclosures of the first entry. The parser captures all enclosures as a list, even though RSS allows at most one per item. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/rss20.xml') >>> e = d.entries[0] >>> len(e.enclosures) 1 >>> e.enclosures[0] {'type': 'audio/mpeg', 'length': '1069871', 'href': 'http://example.org/audio/demo.mp3'} ``` -------------------------------- ### Detecting password-protected feeds via status and headers Source: https://feedparser.readthedocs.io/en/latest/http-authentication Shows how to detect that a feed is password-protected by checking the HTTP status code 401 and the 'www-authenticate' header. The header contains the authentication type (Basic or Digest) and the realm, which are needed to construct the appropriate handler. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/basic_auth.xml') >>> d.status 401 >>> d.headers['www-authenticate'] 'Basic realm="Use test/basic"' >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/digest_auth.xml') >>> d.status 401 >>> d.headers['www-authenticate'] 'Digest realm="DigestTest", nonce="+LV/uLLdAwA=5d77397291261b9ef256b034e19bcb94f5b7992a", algorithm=MD5, qop="auth"' ``` -------------------------------- ### feed.author_detail Source: https://feedparser.readthedocs.io/en/latest/reference-feed-author_detail A dictionary with details about the feed author. It contains the name, href, and email of the author. ```APIDOC ## feed.author_detail ### Description A dictionary with details about the feed author. ### Fields - **name** (string) - The name of the feed author. - **href** (string) - The URL of the feed author. This can be the author's home page, or a contact page with a webmail form. If this is a relative URI, it is resolved according to a set of rules. - **email** (string) - The email address of the feed author. ### Source Elements The email field comes from the following feed elements: - /atom03:feed/atom03:author - /atom10:feed/atom10:author - /rdf:RDF/rdf:channel/dc:author - /rdf:RDF/rdf:channel/dc:creator - /rss/channel/dc:author - /rss/channel/dc:creator - /rss/channel/itunes:author - /rss/channel/managingEditor ### See Also - feed.author ``` -------------------------------- ### feed.info_detail Source: https://feedparser.readthedocs.io/en/latest/reference-feed-info-detail A dictionary with details about the feed info. It contains sub-attributes value, type, language, and base. ```APIDOC ## feed.info_detail ### Description A dictionary with details about the feed info. Comes from /atom03:feed/atom03:info. ### Attributes - **value** - Same as feed.info. If this contains HTML or XHTML, it is sanitized by default. Relative URIs may be resolved according to a set of rules. - **type** - The content type of the feed info. Most likely values: text/plain, text/html, application/xhtml+xml. For Atom feeds, taken from the type attribute (defaults to text/plain). For RSS feeds, auto-determined by inspecting content (defaults to text/html). - **language** - The language of the feed info. Supposed to be a language code per RFC 3066, but may be arbitrary. May come from xml:lang attribute, inherit from parent, or Content-Language HTTP header. If not specified, will be None. - **base** - The original base URI for links within the feed copyright. Useful in rare situations; relative links are already resolved by the parser. ### See Also - feed.info ``` -------------------------------- ### Noticing temporary redirects with feedparser Source: https://feedparser.readthedocs.io/en/latest/http-redirect Shows how to detect a temporary redirect (HTTP 302) using feedparser. The parser automatically follows the redirect, so you can continue using the original URL on subsequent requests. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/temporary.xml') >>> d.status 302 >>> d.href 'http://feedparser.org/docs/examples/atom10.xml' >>> d.feed.title 'Sample Feed' ``` -------------------------------- ### Access namespaced elements with non-standard prefixes in feedparser Source: https://feedparser.readthedocs.io/en/latest/namespace-handling Shows how Universal Feed Parser exposes namespaced elements using the prefix as part of the attribute name (e.g., d.feed.prism_issn). Accessing an unrecognized prefix raises AttributeError, and d.namespaces lists the namespaces found in the feed. ```python >>> import feedparser >>> d = feedparser.parse('https://feedparser.readthedocs.io/en/latest/examples/nonstandard_prefix.rdf') >>> d.feed.prism_issn '0028-0836' >>> d.feed.foo_issn Traceback (most recent call last): File "feedparser\util.py", line 149, in __getattr__ return self.__getitem__(key) File "feedparser\util.py", line 112, in __getitem__ return dict.__getitem__(self, key) KeyError: 'foo_issn' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "", line 1, in File "feedparser\util.py", line 151, in __getattr__ raise AttributeError("object has no attribute '%s'" % key) AttributeError: object has no attribute 'foo_issn' >>> d.namespaces {'': 'http://purl.org/rss/1.0/', 'prism': 'http://prismstandard.org/namespaces/1.2/basic/', 'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'} ``` -------------------------------- ### Register a custom date handler with feedparser.registerDateHandler Source: https://feedparser.readthedocs.io/en/latest/date-parsing Registers a callback that parses a date string in MM/DD/YYYY HH:MM:SS format and returns a 9-tuple Python date in UTC. The handler is tried before built-in handlers, in last-in-first-out order. If it returns None, a non-9-tuple, or raises an exception, the error is silently ignored and other handlers are tried. ```python import feedparser import re _my_date_pattern = re.compile( r'(\d{,2})/(\d{,2})/(\d{4}) (\d{,2}):(\d{2}):(\d{2})') def myDateHandler(aDateString): """parse a UTC date in MM/DD/YYYY HH:MM:SS format""" month, day, year, hour, minute, second = \ _my_date_pattern.search(aDateString).groups() return (int(year), int(month), int(day), \ int(hour), int(minute), int(second), 0, 0, 0) feedparser.registerDateHandler(myDateHandler) d = feedparser.parse(...) ``` -------------------------------- ### RSS description with dangerous CSS style attribute Source: https://feedparser.readthedocs.io/en/latest/html-sanitization Two RSS description samples showing dangerous CSS in style attributes. The first uses a javascript: URL; the second uses an expression() without the javascript: keyword, which Internet Explorer for Windows will still execute. ```html Watch out for <span style="background: url(javascript:window.location='http://example.org/')"> nasty tricks</span> ``` ```html Watch out for <span style="any: expression(window.location='http://example.org/')"> nasty tricks</span> ```