I'm working on a project where I have to extract some basic information from webpages like links, title etc. I can't use any of the awesome libs like `bs4` or my personal favorite `lxml`.<br><br> At first I tried `xml.minidon.parseString()` but it had zero tolerance for broken html. My app needs to parse html from random sources so I have no control over the quality of the html that gets passed to the parser.<br><br>It was suggested to me by a fellow coder to use `html.parse.HTMLParser()`. My first impression of `HTMLParser` was dam this is low level but pretty cool.<br>I wouldn't want to do any advanced scraping with it but its great at extracting basic information from a web page like the title and links. It also seems to be pretty fast. So I figured `HTMLParser()` was the best choice for the job.<br><br> I quickly hacked this parser together and was able to make it do most of what I need it to do.<br> Before I begin expanding this parser I would like to do as much refactoring as possible.<br><br> #-*-coding:utf8;-*- #qpy:3 #qpy:console from html.parser import HTMLParser from urllib.request import urlopen from urllib.parse import urlparse ANCHOR = 'a' TITLE = 'title' META = 'meta' BOLD = 'b' class BasicParser(HTMLParser): recording_title = 0 recording_bold = 0 links = set() bold_text = [] title = None url = None root_url = None resolve_links = 1 def set_url(self, url): parsed_url = urlparse(url) scheme = parsed_url.scheme host = parsed_url.netloc self.root_url = '{}://{}/'.format(scheme, host) self.url = parsed_url.geturl() def handle_starttag(self, tag, attrs): # TODO; flatten this out! if tag == ANCHOR: for attribute in attrs: if attribute[0] == 'href': link = attribute[1] if not self.resolve_links: self.links.append(link) else: if link.startswith('http'): self.links.add(attribute[1]) else: self.links.add(self.root_url + attribute[1]) if tag == TITLE: self.recording_title = 1 else: self.recording_title = 0 if tag == BOLD: self.recording_bold = 1 else: self.recording_bold = 0 def handle_data(self, data): if self.recording_title: self.title = data.strip() if self.recording_bold: self.bold_text.append(data) # example usage. url = 'http://www.cnn.com/' def parse_page(url): p = BasicParser() p.set_url(url) html = urlopen(url).read().decode('latin-1') p.feed(html) return p page = parse_page(url) print(page.title)