7

我正在尝试从 HTML 输入文件中读取行并准备 Series / DataFrames,以便最终可以创建图表。我正在使用 lxml 的 objectify 来获取 HTML 数据行并将它们转换为列表。每当我尝试获取列表数据并制作一个系列或数据框时,我都会得到一个系列(或数据框),其中包含的元素数量等于列表中的项目数,但元素的数据是我的列表本身。

我可以展示我的问题的最简单方法是:

from lxml import etree
from lxml import objectify
from pandas import Series
line='<tr class="alt"><td>192.168.1.0</td><td>XXDHCP</td><td>Y</td><td>255</td><td>0</td><td>YYDHCP</td><td>Y</td><td>250</td><td>0</td><td>0%</td><td>505</td><td>505</td><td>0</td><td></td></tr>'
htmldata=(objectify.fromstring(line)).getchildren()
htmlseries=Series(htmldata)

htmlseries 最终看起来像:

0     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
1     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
2     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
3     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
4     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
5     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
6     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
7     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
8     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
9     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
10    [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
11    [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
12    [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
13    [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...

type(htmldata[0])是:lxml.objectify.StringElement
type(htmldata[3])是:lxml.objectify.IntElement

虽然我正在寻找类似的东西:

0     192.168.1.0
1          XXDHCP
2               Y
3             255
4               0
5          YYDHCP
6               Y
7             250
8               0
9              0%
10            505
11            505
12              0
13               

我究竟做错了什么?我对发生了什么感到有些困惑。当我尝试将每一列读入列表时:

data=objectify.fromstring(line).getchildren()
labdata[ip]['Scope'].append(data[0])
labdata[ip]['Cluster1'].append(data[1])
labdata[ip]['Active1'].append(data[2])
...etc...

我的清单最终看起来像:

labdata['192.168.1.0']['Utilization']
['100%',
 '96%',
 '96%',
 '90%',
 '81%',
 '96%',
 '90%',
 '97%',
 '98%',
 '92%',
 '99%',
 ...etc...
 ]

但由于某种原因:

Series(labdata['192.168.1.0']['Utilization'])
0     [[[192.168.1.0, XXDHCP, Y, 0, 383, YYDHCP, Y...
1     [[[192.168.1.0, XXDHCP, Y, 28, 355, YYDHCP, ...
2     [[[192.168.1.0, XXDHCP, Y, 28, 355, YYDHCP, ...
3     [[[192.168.1.0, XXDHCP, Y, 76, 307, YYDHCP, ...
4     [[[192.168.1.0, XXDHCP, Y, 104, 279, YYDHCP,...
5     [[[192.168.1.0, XXDHCP, Y, 27, 356, YYDHCP, ...
6     [[[192.168.1.0, XXDHCP, Y, 66, 317, YYDHCP, ...
7     [[[192.168.1.0, XXDHCP, Y, 15, 368, YYDHCP, ...
8     [[[192.168.1.0, XXDHCP, Y, 15, 368, YYDHCP, ...
9     [[[192.168.1.0, XXDHCP, Y, 54, 329, YYDHCP, ...
...etc...

type(labdata['192.168.1.0']['Utilization'][0])lxml.objectify.StringElement

我需要将这些元素转换为普通字符串和整数吗?

4

2 回答 2

7

问题是 htmldata 中的元素不是简单类型,并且 np.isscalar 在这里被愚弄了(因为这是它如何确定我们是否有列表列表或标量列表只是将元素字符串化,这将起作用

In [23]: print [ type(x) for x in htmldata ]
[<type 'lxml.objectify.StringElement'>, <type 'lxml.objectify.StringElement'>, <type 'lxml.objectify.StringElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.StringElement'>, <type 'lxml.objectify.StringElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.StringElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.StringElement'>]

In [24]: Series([ str(x) for x in htmldata ])
Out[24]: 
0     192.168.1.0
1          XXDHCP
2               Y
3             255
4               0
5          YYDHCP
6               Y
7             250
8               0
9              0%
10            505
11            505
12              0
13               
于 2013-04-02T17:07:58.400 回答
2

好问题!这是奇怪的行为。

出现问题是因为您正在向 Series 传递 list lxml.objectify.StringElementpandasnp.arrays 支持,因此更喜欢将其数据存储在统一数组中。因此,它将所有内容抽象为一个np.object,以便可以将它们推入一个数组。实际上,如果您查看数据的底层数组 ( Series.values),您会发现它创建得很好,尽管它是一个 numpy 数组,lxml.objectify.StringElements其中可能不是您想要的。

简单的解决方案当然是将所有内容都转换为字符串,这可能是您在这种情况下想要做的。


但你问为什么打印很有趣?好吧,如果你在 pandas 中钻取代码,你最终会得到以下函数pandas.core.common

def _is_sequence(x):
    try:
        iter(x)
        len(x) # it has a length
        return not isinstance(x, basestring) and True
    except Exception:
        return False

换句话说,pandas 看到 lxml 对象不是基本字符串,因此假定它们是序列。熊猫可能应该检查isinstance(x, collections.Sequence)...

于 2013-04-02T17:08:48.603 回答