Python/BeautifulSoup 解析 HTML 分数

标签 python parsing unicode beautifulsoup

问题

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

  2. 从分数到小数 (-1.75) 最简洁的方法是什么?

背景

我正在使用 BeautifulSoupPython 读取一些 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)

因此,我们现在有一个名为 fractiondict,它将 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/

相关文章:

python - 列出数据库的表

python - 属性还是方法?

python - 为 ORTOOLS CP-SAT 中的变量设置可能的唯一值数量

python - 从 AND 到一维数组

parsing - 成分也可以单独使用的求和类型

java - 无法使用 Jsoup 获取重复标签

java - 在java中解析字符串

javascript - 如何在 Javascript 中去除 ‏?

c - 如何使用新的 char16_t 和 u8 类型?

unicode - 比较不同编码的文件