1

问题

  1. 为什么在最后两种情况下的输出都是 unicode,但在一种情况下它显示分数,而在另一种情况下它显示代表分数的其他代码?

  2. 我从分数到小数(-1.75)的最干净的方法是什么?

背景

我正在使用 并BeautifulSoup阅读Python一些输出分数。下面是我用来测试这个问题的 python 代码,以及结果输出。在下面的代码中我有HTML.HTML

print type(c[0])
print c[0]
print type(c[0].get_text())
print c[0].get_text()
print type(re.split(" ", c[0].get_text())[0])
print re.split(" ", c[0].get_text())

这输出:

<class 'bs4.element.Tag'>
<b>-1¾ -101</b>
<type 'unicode'>
-1¾ -101
<type 'unicode'>
[u'-1\xbe\xa0-101']
4

1 回答 1

2

让我们首先解决您问题的简单部分:

打印列表时,repr内容的 用于表示列表中的项目。所以自从

re.split(" ", c[0].get_text())

是一个列表, print 语句打印列表中元素的repr 。unicode

In [63]: x = u'-1\xbe\xa0-101'

In [64]: print(x)
-1¾ -101

In [65]: repr(x)
Out[65]: "u'-1\\xbe\\xa0-101'"

现在是有趣的部分:一些 unicode 代码点有名称。例如,

In [60]: import unicodedata as ud

In [61]: ud.name(u'\xbe')
Out[61]: 'VULGAR FRACTION THREE QUARTERS'

事实上,我们可以在所有 unicode 字符中搜索名称与模式匹配的字符'FRACTION (\w+) (\w+)'

import unicodedata as ud
import re

numerator = {
    'ONE':1,
    'TWO':2,
    'THREE':3,
    'FOUR':4,
    'FIVE':5,
    'SIX':6,
    'SEVEN':7,
    'EIGHT':8,
    'NINE':9,
    'ZERO':0,
    }

denominator = {
    'QUARTER':4,
    'HALF':2,
    'SEVENTH':7,
    'NINTH':9,
    'THIRD':3,
    'FIFTH':5,
    'SIXTH':6,
    'EIGHTH':8,
    'SIXTEENTH':16
    }

fraction = {}
for num in range(0x110000):
    s = unichr(num)
    try:
        name = ud.name(s)
    except ValueError:
        continue
    match = re.search('FRACTION ({n}) ({d})'.format(
        n = '|'.join(numerator.keys()),
        d = '|'.join(denominator.keys()),
        ) , name)
    if match:
        fraction[num] = unicode(
           float(numerator[match.group(1)])/denominator[match.group(2)]).lstrip('0')
print(fraction)

因此,我们现在有一个dict命名fraction,它将 unicode 代码点映射到unicode分数的十进制表示。

{8585: u'.0', 43056: u'.25', 43057: u'.5', 43058: u'.75', 43059: u'.0625', 43060: u'.125', 43061: u'.1875', 188: u'.25', 189: u'.5', 190: u'.75', 8528: u'.142857142857', 8529: u'.111111111111', 8531: u'.333333333333', 8532: u'.666666666667', 8533: u'.2', 8534: u'.4', 8535: u'.6', 8536: u'.8', 8537: u'.166666666667', 8538: u'.833333333333', 8539: u'.125', 8540: u'.375', 8541: u'.625', 8542: u'.875', 69245: u'.333333333333', 3443: u'.25', 3444: u'.5', 3445: u'.75', 69243: u'.5', 69244: u'.25', 11517: u'.5', 69246: u'.666666666667'}

现在你可以u'-1\xbe\xa0-101'这样翻译:

text = u'-1\xbe\xa0-101'
print(text.translate(fraction))    

产量

-1.75 -101

所以简短的回答是:

fraction = {8585: u'.0', 43056: u'.25', 43057: u'.5', 43058: u'.75', 43059: u'.0625', 43060: u'.125', 43061: u'.1875', 188: u'.25', 189: u'.5', 190: u'.75', 8528: u'.142857142857', 8529: u'.111111111111', 8531: u'.333333333333', 8532: u'.666666666667', 8533: u'.2', 8534: u'.4', 8535: u'.6', 8536: u'.8', 8537: u'.166666666667', 8538: u'.833333333333', 8539: u'.125', 8540: u'.375', 8541: u'.625', 8542: u'.875', 69245: u'.333333333333', 3443: u'.25', 3444: u'.5', 3445: u'.75', 69243: u'.5', 69244: u'.25', 11517: u'.5', 69246: u'.666666666667'}
text = c[0].get_text()
text = text.translate(fraction)
parts = map(float, text.split())
print(parts)

产量

[-1.75, -101.0]

请注意,将来可能会为更多的分数分配 unicode 代码点。'FRACTION ({n}) ({d})'也有可能 unicode 代码点的名称与我用来生成fractiondict的模式不匹配。所以我的解决方案有些脆弱,将来可能需要更新。

于 2013-03-03T22:11:13.253 回答