从HTMLparser获取HTML子树

时间:2013-12-03 17:28:17

标签: python python-2.7 html-parsing

我实际上正在使用HTMLparser for python,我正在尝试获取特定节点中包含的HTML子树。 我有一个通用的解析器很好地完成它的工作,一旦找到有趣的标签,我想用另一个特定的HTMLParser提供这个节点中的数据。

这是我想要做的一个例子:

class genericParser(HTMLParser):
   def __init__ (self):
       HTMLParser.__init__(self)
       self.divFound = False

   def handle_starttag (self, tag, attrs):
       if tag == "div" and ("class", "good") in attrs:
           self.divFound = True

   def handle_data (self, data):
       if self.divFound:
           print data    ## print nothing
           parser = specificParser ()
           parser.feed (data)
           self.divFound = False

并为genericParser提供类似的内容:

<html>
<head></head>
<body>
   <div class='good'>
      <ul>
         <li>test1</li>
         <li>test2</li>
      </ul>
   </div>
</body>
</html>

但是在HTMLParser.handle_data的python文档中:

  

调用此方法来处理任意数据(例如文本节点和   <script>...</script><style>...</style>)的内容。

在我的genericParser中,handle_data中的数据为空,因为我的<div class='good'>不是文本节点。

如何使用HTMLParser检索div中的原始HTML数据?

提前致谢

1 个答案:

答案 0 :(得分:1)

我通过缓冲有趣的HTML节点中遇到的所有数据来解决这个问题。

这个可以工作,但不是很“干净”,因为GenericParser必须先解析整个有趣的块,然后才能用它来提供特定的派对。 这是一个“轻”(没有任何错误处理)解决方案:

class genericParser(HTMLParser):
   def __init__ (self):
       HTMLParser.__init__ (self)
       self.divFound = False
       self.buff = ""
       self.level = 0

   def computeRecord (self, tag, attrs):
        mystr = "<" + tag + " "
        for att, val in attrs:
            mystr += att+"='"+val+ "' "
        mystr += ">"
        return mystr

   def handle_starttag (self, tag, attrs):
       if tag == "div" and ("class", "good") in attrs:
           self.divFound = True
       elif self.divFound:
          self.level += 1
          self.buff += self.computeRecord (tag, attrs)

   def handle_data (self, data):
       if self.divFound:
          self.buff += data


   def handle_endtag (self, tag):
      if self.divFound:
         self.buff += "</" + tag + ">"
         self.level -= 1
         if (self.level == 0):
            self.divFound = False
            print self.buff

输出符合要求:

<ul>
     <li>test1</li>
     <li>test2</li>
</ul>

正如Birei在评论中所说,我会更容易用BeautifulSoup

提取子树
soup = BeaufitulSoup (html)
div = soup("div", {"class" : "good"})
children = div[0].findChildren ()
print children[0]   #### desired output