问题
为什么最后两种情况下的输出都是 unicode,但在一种情况下它显示分数,而在另一种情况下它显示代表分数的其他代码?
从分数到小数 (-1.75) 最简洁的方法是什么?
背景
我正在使用 BeautifulSoup
和 Python
读取一些 HTML。
HTML
输出分数。下面是我用来测试这个问题的 python 代码以及结果输出。在下面的代码中我有
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']
最佳答案
让我们先解决问题中最简单的部分:
当您打印列表时,内容的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)
因此,我们现在有一个名为 fraction
的 dict
,它将 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 代码点。也有可能 unicode 代码点的名称与我用来生成分数的模式 'FRACTION ({n}) ({d})'
不匹配> 字典。所以我的解决方案有些脆弱,将来可能需要更新。
关于Python/BeautifulSoup 解析 HTML 分数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15190930/