让HTMLParser区分链接文本和其他数据吗?

时间:2012-02-22 22:38:48

标签: python html-parsing

说我有类似的HTML代码:

<a href="http://example.org/">Stuff I do want</a>
<p>Stuff I don't want</p>

使用HTMLParser的handle_data不区分链接文本(我想要的东西)(这是否是正确的术语?)和我不想要的东西。 HTMLParser是否有内置的方法让handle_data只返回链接文本而没有其他内容?

1 个答案:

答案 0 :(得分:2)

基本上你也必须写一个handle_starttag()方法。只需将您看到的每个标记保存为self.lasttag或其他内容即可。然后,在handle_data()方法中,只需检查self.lasttag并查看它是否为'a'(表示您看到的最后一个标记是HTML锚标记,因此您处于链接中)。

这样的事情(未经测试)应该有效:

from HTMLParser import HTMLParser

class MyHTMLParser(HTMLParser):

    lasttag = None

    def handle_starttag(self, tag, attr):
        self.lasttag = tag.lower()

    def handle_data(self, data):
        if self.lasttag == "a" and data.strip():
            print data

事实上,HTML允许在<a...> ... </a>容器中包含其他标记。并且还可以存在包含文本但不是链接的锚点(没有href=属性)。如果需要,可以处理这些情况。同样,此代码未经测试:

from HTMLParser import HTMLParser

class MyHTMLParser(HTMLParser):

    inlink = False
    data   = []

    def handle_starttag(self, tag, attr):
        if tag.lower() == "a" and "href" in (k.lower() for k, v in attr):
           self.inlink = True
           self.data   = []

    def handle_endtag(self, tag):
        if tag.lower() == "a":
            self.inlink = False
            print "".join(self.data)

    def handle_data(self, data):
        if self.inlink:
            self.data.append(data)

HTMLParser就是你所谓的SAX风格的解析器,它会通知你经过的标签,但是你可以自己跟踪标签层次结构。你可以看到这里的第一版和第二版之间的区别有多复杂。

DOM样式的解析器更容易用于这些类型的任务,因为它们将整个文档读入内存并生成易于导航和搜索的树。 DOM风格的解析器倾向于使用更多内存并且比SAX风格的解析器慢,但现在这比十年前要重要得多。