title: python: get opening and closing html tags
body: <p><strong>Question:</strong></p>
  
  <p>How can I find the text for all opening and closing HTML tags with python (3.6).
  This needs to be the exact text, keeping spaces and potentially illegal html:</p>
  
  <pre><code># input
  html = """&lt;p&gt;This &lt;a href="book"&gt; book &lt;/a  &gt; will help you&lt;/p attr="e"&gt;"""
  
  # desired output
  output = ['&lt;p&gt;', '&lt;a href="book"&gt;', '&lt;/a  &gt;', '&lt;/p attr="e"&gt;']
  </code></pre>
  
  <p><strong>Attempt at solution:</strong></p>
  
  <p>Apparently this is not possible in Beautifulsoup, this question: <a href="https://stackoverflow.com/questions/41597854/how-to-get-the-opening-and-closing-tag-in-beautiful-soup-from-html-string">How to get the opening and closing tag in beautiful soup from HTML string?</a> links to <a href="https://docs.python.org/3.4/library/html.parser.html#example-html-parser-application" rel="nofollow noreferrer">html.parser</a></p>
  
  <p>Implementing a custom parser is easy. You can use <a href="https://docs.python.org/3.4/library/html.parser.html#html.parser.HTMLParser.get_starttag_text" rel="nofollow noreferrer"><code>self.get_starttag_text()</code></a> to get the text corresponding to the last opened tag. But for some reason, there is no analogous method <code>get_endtag_text()</code>.</p>
  
  <p>Which means that my parser produces this output:</p>
  
  <pre><code>class MyHTMLParser(HTMLParser):
      def __init__(self):
          super().__init__()
          self.tags = []
  
      def reset_stored_tags(self):
          self.tags = []
      def handle_starttag(self, tag, attrs):
          self.tags.append(self.get_starttag_text())
  
      def handle_endtag(self, tag):
          self.tags.append(self.get_endtag_text())
  
      def handle_startendtag(self, data):
          self.tags.append(self.get_starttag_text())
  # input
  input_doc = """&lt;p&gt;This &lt;a href="book"&gt; book &lt;/a&gt; will help you&lt;/p&gt;"""
  
  parser = MyHTMLParser()
  parser.feed(input_doc)
  
  print(parser.tags)
  # ['&lt;p&gt;', '&lt;a href="book"&gt;', '&lt;a href="book"&gt;', '&lt;a href="book"&gt;']
  </code></pre>
  
  <p>The <code>tag</code> argument of the <code>handle_endtag</code> is just a string <code>"a"</code> or <code>"p"</code>, not some custom datatype that can provide the whole tag.</p>