To extract links without the overhead of Beautiful Soup, one option is to copy what Beautiful Soup does, and write a SGMLParser subclass that only looks at 'a' tags. In general I think writing SGMLParser subclasses is a big pain (which is why I wrote Beautiful Soup), but since you only care about one type of tag it's not so difficult:
from sgmllib import SGMLParser class LinkParser(SGMLParser): def __init__(self): SGMLParser.__init__(self) self.links = [] self.currentLink = None self.currentLinkText = [] def start_a(self, attrs): #If we encounter a nested a tag, end the current a tag and #start a new one. if self.currentLink != None: self.end_a() for attr, value in attrs: if attr == 'href': self.currentLink = value break if self.currentLink == None: self.currentLink = '' def handle_data(self, data): if self.currentLink != None: self.currentLinkText.append(data) def end_a(self): self.links.append([self.currentLink, "".join(self.currentLinkText)]) self.currentLink = None self.currentLinkText = [] Since this ignores any tags other than 'a', it will strip out all tags from the text within an 'a' tag (this might be what you want, since your example shows an 'img' tag being stripped out). It will also close one 'a' tag when it finds another, rather than attempting to nest them. <a href="foo.php">This text has <b>embedded HTML tags</b></a> => [['foo.php', 'This text has embedded HTML tags']] <a href="foo.php">This text has <a name="anchor">an embedded anchor</a>. => [['foo.php', 'This text has '], ['', 'an embedded anchor']] Alternatively, you can subclass a Beautiful Soup class to ignore all tags except for 'a' tags and the tags that they contain. This will give you the whole Beautiful Soup API, but it'll be faster because Beautiful Soup will only build a model of the parts of your document within 'a' tags. The following code seems to work (and it looks like a good candidate for inclusion in the core package). from BeautifulSoup import BeautifulStoneSoup class StrainedStoneSoup(BeautifulStoneSoup): def __init__(self, interestingTags=["a"], *args): args = list(args) args.insert(0, self) self.interestingMap = {} for tag in interestingTags: self.interestingMap[tag] = True apply(BeautifulStoneSoup.__init__, args) def unknown_starttag(self, name, attrs, selfClosing=0): if self.interestingMap.get(name) or len(self.tagStack) > 1: BeautifulStoneSoup.unknown_starttag(self, name, attrs, selfClosing) def unknown_endtag(self, name): if len(self.tagStack) > 1: BeautifulStoneSoup.unknown_endtag(self, name) def handle_data(self, data): if len(self.tagStack) > 1: BeautifulStoneSoup.handle_data(self, data) -- http://mail.python.org/mailman/listinfo/python-list