我制作了一个简单的HTML解析器,它基本上是来自文档的直接复制。我无法在没有将数据分成多个块的情况下对特殊字符进行转义。
这是我的代码,其中有一个简单的例子:
from HTMLParser import HTMLParser
class MyHTMLParser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.data = []
def handle_starttag(self, tag, attrs):
#print (tag,attrs)
pass
def handle_endtag(self, tag):
#print (tag)
pass
def handle_data(self, data):
self.data.append(data)
def handle_charref(self, ref):
self.handle_entityref("#" + ref)
def handle_entityref(self, ref):
self.handle_data(self.unescape("&%s;" % ref))
n = "<strong>I <3s U & you luvz me</strong>"
parser = MyHTMLParser()
parser.feed(n)
parser.close()
data = parser.data
print(data)
问题是这会返回5个独立的数据位
['I ', u'<', '3s U ', u'&', ' you luvz me']
我想要的是单个字符串:
['I <3s U & you luvz me']
由于 JP
答案 0 :(得分:3)
使用str.join
加入字符串列表:
>>> ''.join(['I ', u'<', '3s U ', u'&', ' you luvz me'])
u'I <3s U & you luvz me'
或者,您可以使用外部库,例如lxml
:
>>> import lxml.html
>>> n = "<strong>I <3s U & you luvz me</strong>"
>>> root = lxml.html.fromstring(n)
>>> root.text_content()
'I <3s U & you luvz me'
答案 1 :(得分:1)
请记住,HTMLParser的目的是让您从输入构建文档树。如果您根本不关心文档的结构,那么str.join
解决方案@falsetru就可以了。您可以确定将过滤掉所有元素标记和注释。
但是,如果确实需要更复杂场景的结构,则必须构建文档树。这里有handle_starttag
和handle_endtag
方法。
首先,我们需要一个可以保存一些信息的基本树。
class Element:
def __init__(self, parent, tag, attrs=None):
self.parent = parent
self.tag = tag
self.children = []
self.attrs = attrs or []
self.data = ''
现在,您需要让HTMLParser在每个handle_starttag
上创建一个新节点,并在每个handle_endtag
上向上移动树。我们还将解析后的数据传递给当前节点,而不是将其保存在解析器中。
class MyHTMLParser(HTMLParser):
def __init__(self):
super().__init__()
self.root = Element(NONE, '__DOCROOT__') # Special root node for us
self.current = self.root
def handle_starttag(self, tag, attrs):
newel = Element(self.current tag, attrs)
self.current.children.append(newel)
self.current = newel
def handle_endtag(self, tag):
self.current = self.current.parent
def handle_data(self, data):
self.current.data += data
def handle_charref(self, ref): # No changes here
self.handle_entityref('#' + ref)
def handle_entityref(self, ref): # No changes here either
self.handle_data(self.unescape("&%s" % ref))
现在,您可以访问MyHTMLParser.root
上的树,以便根据需要从任何元素中获取数据。例如
n = '<strong>I <3s U & you luvz me</strong>'
p = MyHTMLParser()
p.feed(n)
p.close()
def print_tree(node, indent=0):
print(' ' * indent + node.tag)
print(' ' * indent + ' ' + node.data)
for c in node.children:
print_tree(c, indent + 1)
print_tree(p.root)
这会给你
__DOCROOT__
strong
I <3s U & you luvz me
相反,如果您解析n = <html><head><title>Test</title></head><body><h1>I <3s U & you luvz me</h1></body></html>
,您就会得到。
__DOCROOT__
html
head
title
Test
body
h1
I <3s U & you luvz me
接下来是使树构建健壮并处理不匹配或隐式结束标记等情况。您还需要在find('tag')
上添加一些不错的Element
类似方法来遍历树。做得好,你就做了下一个BeautifulSoup。
答案 2 :(得分:1)
您可以参考此answer。
并根据需要修改html_to_text
功能。
from HTMLParser import HTMLParser
n = "<strong>I <3s U & you luvz me</strong>"
class MLStripper(HTMLParser):
def __init__(self):
self.reset()
self.fed = []
def handle_data(self, d):
self.fed.append(d)
def handle_entityref(self, name):
self.fed.append('&%s;' % name)
def get_data(self):
return ''.join(self.fed)
def html_to_text(html):
s = MLStripper()
s.feed(html)
return HTMLParser().unescape(s.get_data())
print html_to_text(n)
输出:
I <3s U & you luvz me