用BeautifulSoup刮取HTML表格

2024-04-24 07:48:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图从英国《金融时报》网站上的一个表格中获取数据,但我无法让代码正常工作。我已经在这里讨论过关于堆栈溢出的其他类似问题,虽然它们有帮助,但我无法让代码正常工作。在

我想把表刮干净,然后输出到dict列表,或者dict的dict,然后将其放入pandas数据帧中。在

为清晰起见进行编辑:

我想:

  1. 擦桌子
  2. 去掉html标记
  3. 返回dict where 每行的第一个单元格是键,其余单元格是 钥匙

到目前为止,我可以做(1),(2)我认为这是一个清理工作,应该不会太难,(3)是我有问题的地方。有些行只包含一个条目,因为它们是节标题,但在html中没有这样标记,所以我在其他答案中看到的标准dict理解返回错误,因为key没有值,或者将第一个条目设置为所有其他数据的键。在

表是here。在

到目前为止,我的代码是:

from bs4 import BeautifulSoup
import urllib2
import lxml

soup = BeautifulSoup(urllib2.urlopen('http://markets.ft.com/research/Markets/Tearsheets/Financials?s=CLLN:LSE&subview=BalanceSheet').read())



table = soup.find('table', {'data-ajax-content' : 'true'})


for row in table.findAll('tr'):
    for cell in row.findAll('td'):
        print cell.findAll(text = True)

我得到了这样的输出:

^{pr2}$

我试过:

rows = iter(table)

headers = [col.text for col in next(rows)]

for row in rows:
    values = [col.text for col in row]
    print dict(zip(headers, values))

可能有用,但我得到了:

urllib2.HTTPError: HTTP Error 407: Proxy Authorization Required,

我想是因为我是公司代理人。在

编辑:

我在家里试过上面的代码,结果是:

{u'Fiscal data as of Dec 31 2013201320122011': u'ASSETS'}
{u'Fiscal data as of Dec 31 2013201320122011': u'LIABILITIES'}
{u'Fiscal data as of Dec 31 2013201320122011': u'SHAREHOLDERS EQUITY'}

这是诱人的接近,但只捕获了每一部分的第一行。在

非常感谢任何帮助。我是python新手,所以如果你有时间解释你的答案,我也会很感激。在

编辑:

我读了更多的书,尝试了更多的东西:

table = soup.find('table', {'data-ajax-content' : 'true'})

rows = table.findAll('tr')

dict_for_series = {row[0]:row[1:] for row in rows}

print dict_for_series

结果是:

{<tr><td class="label">Fiscal data as of Dec 31 2013</td><td>2013</td><td>2012</td><td>2011</td></tr>: [<tr class="section even"><td colspan="4">ASSETS</td></tr>, <tr class="odd"><td class="label">Cash And Short Term Investments</td><td>416</td><td>660</td><td>495</td></tr>, <tr class="even"><td class="label">Total Receivables, Net</td><td>1,216</td><td>1,122</td><td>1,102</td></tr>, <tr class="odd"><td class="label">Total Inventory</td><td>49</td><td>55</td><td>72</td><

在本例中,代码似乎将第一个条目设置为键,其余条目设置为值。在

另一次尝试:

table = soup.find('table', {'data-ajax-content' : 'true'})

rows = table.findAll('tr')


d = []

for row in rows:
    d.append(row.findAll('td'))

rowsdict = {t[0]:t[1:] for t in d}

dictSer = Series(rowsdict)

dictframe = DataFrame(dictSer)

print dictframe

结果是:

0
<td class="label">Fiscal data as of Dec 31 2013</td>                     [<td>2013</td>, <td>2012</td>, <td>2011</td>]
<td colspan="4">ASSETS</td>                                                                                         []
<td class="label">Cash And Short Term Investments</td>                      [<td>416</td>, <td>660</td>, <td>495</td>]
<td class="label">Total Receivables, Net</td>                         [<td>1,216</td>, <td>1,122</td>, <td>1,102</td>]

这与我想要的非常接近,结构几乎是正确的,但是从方括号的位置来看,这是将所有的值即<td>1,216</td>视为一个单元格。在

不管怎样,我会继续玩,努力让它成功,但是如果有人有任何建议,请告诉我!在


Tags: 代码infordataastablelabeltr