【问题标题】:Extract data from HTML table using Python使用 Python 从 HTML 表中提取数据
【发布时间】:2011-10-16 05:19:31
【问题描述】:

我想使用 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 变量与最大时间进行比较,因此它失败了,因为它们是浮点数。

【问题讨论】:

  • “还有一件事,我不想使用外部库”。史诗般的失败。你真的必须使用美丽的汤。这是最适合这种事情的。
  • 好吧,如果没有其他出路,那我就用美汤吧:)
  • “来自 HTML”是 Beautiful Soup 的代名词。

标签: python html extract


【解决方案1】:

好吧,如果你的 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 文件将是一项艰巨的工作。

【讨论】:

【解决方案2】:

使用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"

【讨论】:

  • lxml 是一个外部库,不是吗?根据@Marko Python 版本,他可以改用ElementTree,或者 - 呃.... - xml.dom.minidom
  • @brandizzi:在 cmets Marko 表示愿意使用 BeautifulSoup。我认为这意味着愿意使用任何外部库。
  • 感谢 unutbu,这是我的最终代码,我仍然使用外部库:if (not os.path.exists(Filename)): download = urllib2.urlopen(MonitorURL) data = download.read() fileObj = open(Filename, "w") tree = lh.fromstring(data) for key, status, time in zip(*[iter(tree.xpath('//td/text()'))]*3): fileObj.writelines('''{k}_STATUS = "{s}"\n'''.format(k=key,s=status)) fileObj.writelines('''{k}_TIME = "{t}"\n'''.format(k=key,t=time.rstrip(' s'))) fileObj.close()
猜你喜欢
  • 2013-06-12
  • 1970-01-01
  • 1970-01-01
  • 2020-10-17
  • 2015-06-10
  • 1970-01-01
  • 1970-01-01
  • 2020-10-29
  • 1970-01-01
相关资源
最近更新 更多