在回复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>Hello</h1>after')
这样做我想知道这个模块的API是不好还是我没注意到一些重要的事情。我的问题是:
handle_charref
的实施必须那么复杂?我原本期望一个好的API将代码点作为参数传递,而不是x6c
或72
作为字符串。handle_charref
的默认实现不会使用适当的字符串调用handle_data
?handle_entityref
的实用程序实现?它可以命名为handle_entityref_HTML4
,并查找HTML 4中定义的实体,然后在其上调用handle_data
。如果提供了该API,编写自定义HTML解析器会更容易。那我的误会在哪里?
答案 0 :(得分:1)
嗯,我倾向于同意,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行代码中的最小值。添加异常处理可能会使其行数增加一倍。
答案 1 :(得分:0)
您是否需要实现自己的解析器,或者您已经创建了?请看beautiful soup。