自定义HTMLParser处理含&字符文本时输出为空的解决方案咨询
解决方案
问题根因
- 自定义
HTMLParser没有在feed操作完成后调用close()方法,未闭合的实体引用(即&后没有匹配的;结尾的内容)会被HTMLParser滞留在缓冲区,不会触发handle_data回调,因此出现输出缺失甚至为空的问题。 - 当
convert_charrefs设为False时,HTMLParser不会自动转换实体引用,未闭合的&后的内容仍会被识别为待解析的实体标记,不会进入handle_data,因此只能输出&之前的内容。
修复方案
最小改动方案(仅加1行代码,适配绝大多数场景)
仅需要在strip_tags函数中新增close()调用,强制解析缓冲区剩余内容即可,原有处理逻辑完全不变:
from html.parser import HTMLParser from io import StringIO class MyParser(HTMLParser): def __init__(self): super().__init__() self.reset() self.strict = False self.convert_charrefs= True self.text = StringIO() def handle_data(self, d): self.text.write(d) def get_data(self): return self.text.getvalue() def strip_tags(html): s = MyParser() s.feed(html) s.close() # 仅新增这一行 return s.get_data() # 测试输出 strip_tags("Q&A") # 输出:Q&A strip_tags("String&Otherstring") # 输出:String&Otherstring strip_tags("<div>测试HTML内容<p>嵌套标签</p></div>") # 原有正常场景不受影响,输出:测试HTML内容嵌套标签
保留原始实体编码方案
如果需要原样保留&这类实体编码不自动转义为&,可以再新增两个实体处理回调方法,改动同样极小:
class MyParser(HTMLParser): def __init__(self): super().__init__() self.reset() self.strict = False self.convert_charrefs= False self.text = StringIO() def handle_data(self, d): self.text.write(d) # 新增实体处理方法,原样输出实体编码 def handle_entityref(self, name): self.text.write(f'&{name};') def handle_charref(self, name): self.text.write(f'&#{name};') def get_data(self): return self.text.getvalue() def strip_tags(html): s = MyParser() s.feed(html) s.close() return s.get_data() # 测试输出 strip_tags("Q&A") # 输出:Q&A strip_tags("Q&A") # 输出:Q&A
内容的提问来源于stack exchange,提问作者Paolo Magnani
相关产品推荐
相关产品推荐

