在Python 2.7中将½解析为0.5

时间:2016-01-26 11:12:01

标签: python python-2.7 beautifulsoup

我正在使用BeautifulSoup4

抓取this link

我正在解析像这样的页面HTML

page = BeautifulSoup(page.replace('ISO-8859-1', 'utf-8'),"html5lib")

您可以看到这些值-4 -115(由-分隔)

我想要列表中的两个值,所以我使用这个正则表达式。

value = re.findall(r'[+-]?\d+', value)

它完美无缺,但不适用于这些值+2½ -102,我只获得[-102]

要解决这个问题,我也尝试了这个

value = value.replace("½","0.5")
value = re.findall(r'[+-]?\d+', value)

但这给了我关于编码的错误,说我必须设置我的文件的编码。

我还尝试在文件顶部设置encoding=utf-8,但仍会出现同样的错误。

我需要问一下如何将½转换为0.5

3 个答案:

答案 0 :(得分:7)

要在Python 2脚本中嵌入像½这样的Unicode文字,您需要在脚本顶部使用特殊注释,让解释器知道Unicode的编码方式。如果您想使用UTF-8,您还需要告诉编辑器将文件保存为UTF-8。如果要打印Unicode文本,请确保您的终端也设置为使用UTF-8。

这是一个简短的例子,在Python 2.6.6上进行了测试

# -*- coding: utf-8 -*-

value = "a string with fractions like 2½ in it"
value = value.replace("½",".5")
print(value)

<强>输出

a string with fractions like 2.5 in it

请注意,我使用".5"作为替换字符串;使用"0.5"会将"2½"转换为"20.5",这是不正确的。

实际上,这些字符串应该标记为Unicode字符串,如下所示:

# -*- coding: utf-8 -*-

value = u"a string with fractions like 2½ in it"
value = value.replace(u"½", u".5")
print(value)

有关在Python中使用Unicode的更多信息,请参阅由SO资深人士Ned Batchelder撰写的Pragmatic Unicode

我还应该提一下,你需要改变你的正则表达式模式,以便它允许数字中的小数点。例如:

# -*- coding: utf-8 -*-
from __future__ import print_function
import re

pat = re.compile(r'[-+]?(?:\d*?[.])?\d+', re.U) 

data = u"+2½ -105 -2½ -115 +2½ -105 -2½ -115 +2½ -102 -2½ -114"
print(data)
print(pat.findall(data.replace(u"½", u".5")))

<强>输出

+2½ -105 -2½ -115 +2½ -105 -2½ -115 +2½ -102 -2½ -114
[u'+2.5', u'-105', u'-2.5', u'-115', u'+2.5', u'-105', u'-2.5', u'-115', u'+2.5', u'-102', u'-2.5', u'-114']

答案 1 :(得分:4)

Unicode中有更多的粗俗分数而不仅仅是½,这里有一些代码可以解析所有:

# coding=utf8

# curl -s "http://www.unicode.org/Public/UNIDATA/extracted/DerivedNumericValues.txt" | grep "VULGAR FRACTION"
fractions = {
    0x2189: 0.0,  # ; ; 0 # No       VULGAR FRACTION ZERO THIRDS
    0x2152: 0.1,  # ; ; 1/10 # No       VULGAR FRACTION ONE TENTH
    0x2151: 0.11111111,  # ; ; 1/9 # No       VULGAR FRACTION ONE NINTH
    0x215B: 0.125,  # ; ; 1/8 # No       VULGAR FRACTION ONE EIGHTH
    0x2150: 0.14285714,  # ; ; 1/7 # No       VULGAR FRACTION ONE SEVENTH
    0x2159: 0.16666667,  # ; ; 1/6 # No       VULGAR FRACTION ONE SIXTH
    0x2155: 0.2,  # ; ; 1/5 # No       VULGAR FRACTION ONE FIFTH
    0x00BC: 0.25,  # ; ; 1/4 # No       VULGAR FRACTION ONE QUARTER
    0x2153: 0.33333333,  # ; ; 1/3 # No       VULGAR FRACTION ONE THIRD
    0x215C: 0.375,  # ; ; 3/8 # No       VULGAR FRACTION THREE EIGHTHS
    0x2156: 0.4,  # ; ; 2/5 # No       VULGAR FRACTION TWO FIFTHS
    0x00BD: 0.5,  # ; ; 1/2 # No       VULGAR FRACTION ONE HALF
    0x2157: 0.6,  # ; ; 3/5 # No       VULGAR FRACTION THREE FIFTHS
    0x215D: 0.625,  # ; ; 5/8 # No       VULGAR FRACTION FIVE EIGHTHS
    0x2154: 0.66666667,  # ; ; 2/3 # No       VULGAR FRACTION TWO THIRDS
    0x00BE: 0.75,  # ; ; 3/4 # No       VULGAR FRACTION THREE QUARTERS
    0x2158: 0.8,  # ; ; 4/5 # No       VULGAR FRACTION FOUR FIFTHS
    0x215A: 0.83333333,  # ; ; 5/6 # No       VULGAR FRACTION FIVE SIXTHS
    0x215E: 0.875,  # ; ; 7/8 # No       VULGAR FRACTION SEVEN EIGHTHS
}

rx = r'(?u)([+-])?(\d*)(%s)' % '|'.join(map(unichr, fractions))

test = u'15⅑ and ¼ and +212½ and -⅜'

import re

for sign, d, f in re.findall(rx, test):
    sign = -1 if sign == '-' else 1
    d = int(d) if d else 0
    number = sign * (d + fractions[ord(f)])
    print 'found', number

答案 2 :(得分:1)

如果您需要疯狂地使用正则表达式,那么您可以使用unicode char,如下所示。这个unicode名称是 Unicode Character&#39; VULGAR FRACTION ONE HALF&#39; (U + 00BD)详见here

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re

txt = u'-½ -103+½ -113-½ -105+½ -115-½ -105+½ -115 My test for Fraction -1½ -115'

print ''.join(re.findall(u'[+-]?[\d+]?\u00BD?',txt))

#for replacing

print re.sub(ur'\u00BD',ur'.5',txt)

输出 -

-½-103+½-113-½-105+½-115-½-105+½-115-1½-115
-.5 -103+.5 -113-.5 -105+.5 -115-.5 -105+.5 -115 My test for Fraction -1.5 -115

<强> N.B。您可以根据需要修改脚本,但可能需要更改 VULGAR FRACTION - 您将在上面发布的域中获得这些编码。