加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

在Python中有效地使用HTMLParser

发布时间:2020-12-20 13:21:32 所属栏目:Python 来源:网络整理
导读:为响应 Python regular expression,我尝试使用HTMLParser实现HTML解析器: import HTMLParserclass ExtractHeadings(HTMLParser.HTMLParser): def __init__(self): HTMLParser.HTMLParser.__init__(self) self.text = None self.headings = [] def is_releva
为响应 Python regular expression,我尝试使用HTMLParser实现HTML解析器:

import HTMLParser

class ExtractHeadings(HTMLParser.HTMLParser):

  def __init__(self):
    HTMLParser.HTMLParser.__init__(self)
    self.text = None
    self.headings = []

  def is_relevant(self,tagname):
    return tagname == 'h1' or tagname == 'h2'

  def handle_starttag(self,tag,attrs):
    if self.is_relevant(tag):
      self.in_heading = True
      self.text = ''

  def handle_endtag(self,tag):
    if self.is_relevant(tag):
      self.headings += [self.text]
      self.text = None

  def handle_data(self,data):
    if self.text != None:
      self.text += data

  def handle_charref(self,name):
    if self.text != None:
      if name[0] == 'x':
        self.text += chr(int(name[1:],16))
      else:
        self.text += chr(int(name))

  def handle_entityref(self,name):
    if self.text != None:
      print 'TODO: entity %s' % name

def extract_headings(text):
  parser = ExtractHeadings()
  parser.feed(text)
  return parser.headings

print extract_headings('abdk3<h1>The content we need</h1>aaaaabbb<h2>The content we need2</h2>')
print extract_headings('before<h1>&#72;e&#x6c;&#108;o</h1>after')

这样做我想知道这个模块的API是坏还是我没注意到一些重要的事情.我的问题是:

>为什么我的handle_charref实现必须那么复杂?我原本期望一个好的API将代码点作为参数传递,而不是x6c或72作为字符串.
>为什么handle_charref的默认实现没有用适当的字符串调用handle_data?
>为什么没有我可以调用的handle_entityref的实用程序实现?它可以命名为handle_entityref_HTML4,并查找HTML 4中定义的实体,然后在它们上调用handle_data.

如果提供了该API,则编写自定义HTML解析器会更容易.那我的误会在哪里?

解决方法

好吧,我倾向于同意HTMLParser的一个可怕的疏忽,即不包括将HTML实体引用转换为普通ASCII和/或其他字符的代码.我认为这可以通过Python3中完全不同的工作来解决.

但是,似乎我们可以写一个相当简单的实体处理程序,如:

import htmlentitydefs
def entity2char(x):
    if x.startswith('&#x'):
        # convert from hexadecimal
        return chr(int(x[3:-1],16))
    elif x.startswith('&#'):
        # convert from decimal
        return chr(int(x[2:-1]))
    elif x[1:-1] in htmlentitydefs.entitydefs:
        return htmlentitydefs.entitydefs[x[1:-1]]
    else:
        return x

…虽然我们应该进行进一步的输入验证,并在异常处理代码中包装整数转换.

但是这应该处理大约10行代码中的最小值.添加异常处理可能会使其行数增加一倍.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读