2011-07-29 89 views
4

我想使用Python脚本从HTML表格中提取数据,并将其作为变量保存(如果它们存在后,我可以在相同的脚本中使用它们)到一个单独的文件中。另外我希望脚本忽略表格的第一行(组件,状态,时间/错误)。我宁愿不使用外部库。使用Python从HTML表格中提取数据

输出到一个新文件应该像这样:

SAVE_DOCUMENT_STATUS = "OK" 
SAVE_DOCUMENT_TIME = "0.408" 
GET_DOCUMENT_STATUS = "OK" 
GET_DOCUMENT_TIME = "0.361" 
... 

而且继承人的输入脚本:

<table border=1> 
<tr> 
<td><b>Component</b></td> 
<td><b>Status</b></td> 
<td><b>Time/Error</b></td> 
</tr> 
<tr><td>SAVE_DOCUMENT</td><td>OK</td><td>0.408 s</td></tr> 
<tr><td>GET_DOCUMENT</td><td>OK</td><td>0.361 s</td></tr> 
<tr><td>DVK_SEND</td><td>OK</td><td>0.002 s</td></tr> 
<tr><td>DVK_RECEIVE</td><td>OK</td><td>0.002 s</td></tr> 
<tr><td>GET_USER_INFO</td><td>OK</td><td>0.135 s</td></tr> 
<tr><td>NOTIFICATIONS</td><td>OK</td><td>0.002 s</td></tr> 
<tr><td>ERROR_LOG</td><td>OK</td><td>0.001 s</td></tr> 
<tr><td>SUMMARY_STATUS</td><td>OK</td><td>0.913 s</td></tr> 
</table> 

我试图做到这一点在bash,但因为我需要将* _TIME变量与最大时间进行比较,然后失败,因为它们是浮点数。

+3

“还有一两件事,我不想使用外部库”。史诗失败。你真的必须使用美丽的汤。这是最好的这种事情。 –

+0

好吧,如果没有其他出路,我会用美丽的汤:) – Marko

+0

“从HTML”是美丽的汤的代名词。 – SingleNegationElimination

回答

4

使用lxml

import lxml.html as lh 

content='''\ 
<table border=1> 
<tr> 
<td><b>Component</b></td> 
<td><b>Status</b></td> 
<td><b>Time/Error</b></td> 
</tr> 
<tr><td>SAVE_DOCUMENT</td><td>OK</td><td>0.408 s</td></tr> 
<tr><td>GET_DOCUMENT</td><td>OK</td><td>0.361 s</td></tr> 
<tr><td>DVK_SEND</td><td>OK</td><td>0.002 s</td></tr> 
<tr><td>DVK_RECEIVE</td><td>OK</td><td>0.002 s</td></tr> 
<tr><td>GET_USER_INFO</td><td>OK</td><td>0.135 s</td></tr> 
<tr><td>NOTIFICATIONS</td><td>OK</td><td>0.002 s</td></tr> 
<tr><td>ERROR_LOG</td><td>OK</td><td>0.001 s</td></tr> 
<tr><td>SUMMARY_STATUS</td><td>OK</td><td>0.913 s</td></tr> 
</table> 
''' 
tree=lh.fromstring(content) 
for key, status, t in zip(*[iter(tree.xpath('//td/text()'))]*3): 
    print('''{k}_STATUS = "{s}" 
{k}_TIME = "{t}"'''.format(k=key,s=status,t=t.rstrip(' s'))) 

产生

SAVE_DOCUMENT_STATUS = "OK" 
SAVE_DOCUMENT_TIME = "0.408" 
GET_DOCUMENT_STATUS = "OK" 
GET_DOCUMENT_TIME = "0.361" 
DVK_SEND_STATUS = "OK" 
DVK_SEND_TIME = "0.002" 
DVK_RECEIVE_STATUS = "OK" 
DVK_RECEIVE_TIME = "0.002" 
GET_USER_INFO_STATUS = "OK" 
GET_USER_INFO_TIME = "0.135" 
NOTIFICATIONS_STATUS = "OK" 
NOTIFICATIONS_TIME = "0.002" 
ERROR_LOG_STATUS = "OK" 
ERROR_LOG_TIME = "0.001" 
SUMMARY_STATUS_STATUS = "OK" 
SUMMARY_STATUS_TIME = "0.913" 
+0

lxml是一个外部库,不是?根据@Marko Python版本,他可以使用[ElementTree](http://docs.python.org/library/xml.etree.elementtree.html),或者 - urgh .... - [xml.dom.minidom ](http://docs.python.org/library/xml.dom.minidom.html) – brandizzi

+1

@brandizzi:在评论中,Marko表示愿意使用BeautifulSoup。我认为这意味着愿意使用任何外部库。 – unutbu

+0

这里是我的最终代码感谢unutbu,我仍然使用外部库: 'if(not os.path.exists(Filename)): download = urllib2.urlopen(MonitorURL) data = download。读取() fileObj = open(文件名,“w”) 树= lh.fromstring(数据) 对于密钥,状态,时间在zip(* [iter(tree.xpath('// td/text()' ))* 3): fileObj.writelines('''{k} _STATUS =“{s}”\ n'''。格式(k = key,s =状态)) fileObj.writelines(''' {k} _TIME =“{t}”\ n'''。format(k = key,t = time.rstrip('s'))) fileObj.close – Marko

2

好吧,如果你的HTML文档真的有这样稳定的结构(这让我抓我的头,因为它是非常罕见的),你可以使用正则表达式:

>>> import re 
>>> r = re.compile('<tr><td>(.*)</td><td>(.*)</td><td>(.*) s</td></tr>') 

以下组的正则表达式的值要在结果中显示。然后你使用该对象的sub()方法。如果文字是一个变量(如content)只是执行这种方式:

r.sub(r'\1_STATUS = "\2"\n\1_TIME = \3', content) 

结果:

>>> print r.sub(r'\1_STATUS = "\2"\n\1_TIME = \3', content) 
<table border=1> 
<tr> 
<td><b>Component</b></td> 
<td><b>Status</b></td> 
<td><b>Time/Error</b></td> 
</tr> 
SAVE_DOCUMENT_STATUS = "OK" 
SAVE_DOCUMENT_TIME = 0.408 
GET_DOCUMENT_STATUS = "OK" 
GET_DOCUMENT_TIME = 0.361 
DVK_SEND_STATUS = "OK" 
DVK_SEND_TIME = 0.002 
DVK_RECEIVE_STATUS = "OK" 
DVK_RECEIVE_TIME = 0.002 
GET_USER_INFO_STATUS = "OK" 
GET_USER_INFO_TIME = 0.135 
NOTIFICATIONS_STATUS = "OK" 
NOTIFICATIONS_TIME = 0.002 
ERROR_LOG_STATUS = "OK" 
ERROR_LOG_TIME = 0.001 
SUMMARY_STATUS_STATUS = "OK" 
SUMMARY_STATUS_TIME = 0.913 
</table> 

当然,也有很多在字符串中的垃圾还没有,但它给出的想法:)

但是,如果你的HTML文件不稳定,你应该真的考虑一些XML解析器,或者更好的是BeautifulSoup,因为处理结构不稳定的HTML文件用手。

+0

-1 http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 – SingleNegationElimination

+0

我给的HTML是稳定的:)脚本是需要的让这款古老的HTML可以被Nagios使用。 – Marko

+0

@TokenMacGuy虽然我一般同意,我与[这个答案](http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1733489#1733489 )在这种情况下:) – brandizzi