我是lxml和python的新手。我正在尝试解析一个html文档。当我使用标准的xml解析器进行解析时,它会正确地写出字符,但我认为它无法解析,因为我在使用xpath搜索时遇到了问题。
正在解析的示例文件:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>title</title>
</head>
<body>
<span id="demo">Garbléd charactérs</span>
</body>
</html>
解析代码:
from lxml import etree
fname = 'output/so-help.html'
# parse
hparser = etree.HTMLParser()
htree = etree.parse(fname, hparser)
# garbled
htree.write('so-dumpu.html', encoding='utf-8')
# targets
demo_name = htree.xpath("//span[@id='demo']")
# garbled
print 'name: "' + demo_name[0].text
终端输出:
name: "Garbléd charactérs
htree.write输出:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>title</title></head><body>
<span id="demo">Garbléd charactérs</span>
</body></html>
问题是您试图对已经编码的数据进行编码,您需要的是解析器使用utf-8对数据进行解码。*在您的原始代码中,尝试demo_name[0].text.decode('utf-8'),您将看到
正确的方法:
from lxml import etree
fname = 'output/so-help.html'
# parse
hparser = etree.HTMLParser(encoding='utf-8')
htree = etree.parse(fname, hparser)
# garbled
htree.write('so-dumpu.html')
# targets
demo_name = htree.xpath("//span[@id='demo']")
# garbled
print 'name: "' + demo_name[0].text
尝试更改输出编码:
htree.write('so-dumpu.html', encoding='latin1')
和
print 'name: "' + demo_name[0].text.encode('latin1')
我假设XHTML文档是用utf-8编码的。问题是HTML文档中没有指定编码。默认情况下,浏览器和lxml.html假设html文档是用ISO-8859-1编码的,这就是为什么您的文档被错误地解析的原因。如果您在浏览器中打开它,它也会显示错误。
您可以这样指定文档的编码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>title</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
您可以通过这种方式强制lxml使用的编码(就像您可以更改浏览器中使用的编码一样):
file = open(fname)
filecontents = file.read()
filecontents = filecontents.decode("utf-8")
htree = lxml.html.fromstring(filecontents)
print htree.xpath("//span[@id='demo']")[0].text