lxml
(正如观察到的,这在系统编码之间有点狡猾,并且显然在 Windows XP 中不能正常工作,尽管在 Linux 中可以正常工作。)
我通过解码源字符串让它工作 -tree = html.fromstring(source.decode('utf-8'))
:
# -*- coding:cp1251 -*-
import lxml
from lxml import html
filename = "t.html"
fread = open(filename, 'r')
source = fread.read()
tree = html.fromstring(source.decode('utf-8'))
fread.close()
tags = tree.xpath('//span[@class="one" and text()="Text"]') #This OK
print "name: ",tags[0].text
print "value: ",tags[0].tail
tags = tree.xpath('//span[@class="two" and text()="Привет"]') #This is now OK too
print "name: ",tags[0].text
print "value: ",tags[0].tail
这意味着实际的树是全部unicode
对象。如果您只是将 xpath 参数作为unicode
它找到 0 个匹配项。
美丽汤
无论如何,我更喜欢使用 BeautifulSoup 来处理此类事情。这是我的互动环节;我将文件保存在 cp1251 中。
>>> from BeautifulSoup import BeautifulSoup
>>> filename = '/tmp/cyrillic'
>>> fread = open(filename, 'r')
>>> source = fread.read()
>>> source # Scary
'<html>\n<body>\n<span class="one">Text</span>some text</br>\n<span class="two">\xcf\xf0\xe8\xe2\xe5\xf2</span>\xd2\xe5\xea\xf1\xf2 \xed\xe0 \xf0\xf3\xf1\xf1\xea\xee\xec</br>\n</body>\n</html>\n'
>>> source = source.decode('cp1251') # Let's try getting this right.
u'<html>\n<body>\n<span class="one">Text</span>some text</br>\n<span class="two">\u041f\u0440\u0438\u0432\u0435\u0442</span>\u0422\u0435\u043a\u0441\u0442 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c</br>\n</body>\n</html>\n'
>>> soup = BeautifulSoup(source)
>>> soup # OK, that's looking right now. Note the </br> was dropped as that's bad HTML with no meaning.
<html>
<body>
<span class="one">Text</span>some text
<span class="two">Привет</span>Текст на русском
</body>
</html>
>>> soup.find('span', 'one').findNextSibling(text=True)
u'some text'
>>> soup.find('span', 'two').findNextSibling(text=True) # This looks a bit daunting ...
u'\u0422\u0435\u043a\u0441\u0442 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c'
>>> print _ # ... but it's not, really. Just Unicode chars.
Текст на русском
>>> # Then you may also wish to get things by text:
>>> print soup.find(text=u'Привет').findParent().findNextSibling(text=True)
Текст на русском
>>> # You can't get things by attributes and the contained NavigableString at the same time, though. That may be a limitation.
最后,可能值得考虑尝试source.decode('cp1251')
代替source.decode('utf-8')
当您从文件系统中获取它时。那么 lxml 可能真的可以工作。