【问题标题】:How to solve problem with parsing html file with cyrillic symbol?如何解决解析带有西里尔符号的html文件的问题?
【发布时间】:2011-05-10 00:30:42
【问题描述】:

我有一些带有 span 元素的 html 文件:

<html>
<body>
<span class="one">Text</span>some text</br>
<span class="two">Привет</span>Текст на русском</br>
</body>
</html>

获取“一些文本”:

# -*- coding:cp1251 -*-
import lxml
from lxml import html

filename = "t.html"
fread = open(filename, 'r')
source = fread.read()

tree = html.fromstring(source)
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 False

print "name: ",tags[0].text
print "value: ",tags[0].tail

这个节目:

name: Text
value: some text

Traceback: ... in line `tags = tree.xpath('//span[@class="two" and text()="Привет"]')`
    ValueError: All strings must be XML compatible: Unicode or ASCII, no NULL bytes

如何解决这个问题?

【问题讨论】:

    标签: python parsing lxml


    【解决方案1】:

    试试这个

    tree = html.fromstring(source.decode('utf-8'))
    

    tags = tree.xpath('//span[@class="two" and text()="%s"]' % u'Привет' )
    

    【讨论】:

      【解决方案2】:

      我在使用 lxml 生成 XML 时遇到了同样的错误。在这里找到解决方案:http://lethain.com/stripping-illegal-characters-from-xml-in-python/

      我刚做的:

      remove_re = re.compile(u'[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]')
      etree_sub_el.text = remove_re.sub('', text)
      

      【讨论】:

        【解决方案3】:

        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 可能真的可以工作。

        【讨论】:

        • 我是在 Linux 上完成的。等一下,我将启动我的 XP 虚拟机,看看能否在 XP 上解决问题。
        • 谢谢克里斯!在 XP 下这是 ANSI 文件。
        • 实际上,我的虚拟机中没有安装 lxml,而且我也懒得安装(我知道,应该受到谴责)。我会在我的答案中添加一些 BeautifulSoup 代码,希望它适合你。
        • ) 好的,这不是问题。 2 小时后,我将在我的 Linux 下尝试。感谢您的帮助和时间。
        • 尝试source.decode('cp1251') 而不是source.decode('utf-8')。它可能会起作用。如果没有,那就和 BeautifulSoup 一起玩吧……这很有趣,而且你会学到一些东西,即使你没有成功地得到你想要的东西。
        【解决方案4】:

        尚未测试,但在 unicode() 内置函数中包装对 tags[0].tail 的调用应该可以做到:unicode(tags[0].tail)

        【讨论】:

        • 这一行的问题:tags = tree.xpath('//span[@class="two" and text()="Привет"]')
        • 好吧,那text()=u"Привет" 怎么办,如果不这样做text() = unicode("Привет")
        • 我尝试了这些选项。同样的结果。我的 ASCII 格式的 html 文件和 ASCII 格式的 python 脚本。我尝试将其转换为 UTF-8,但什么也没做。 ((也许我不明白一些编解码器路由?
        猜你喜欢
        • 1970-01-01
        • 2021-11-10
        • 2020-10-12
        • 1970-01-01
        • 2021-10-14
        • 1970-01-01
        • 2012-07-17
        • 1970-01-01
        • 2016-10-02
        相关资源
        最近更新 更多