【问题标题】:Extract HTML table using Python BeautifulSoup使用 Python BeautifulSoup 提取 HTML 表格
【发布时间】:2015-05-10 17:23:03
【问题描述】:

我正在尝试从网页中提取表格。下面是使用 beautifulsoup 的 HTML 和 Python 代码。下面的代码总是对我有用,但在这种情况下我会变得空白。提前致谢。

<table>
<thead>
<tr>
<th>Period Ending:</th>
<th class="TalignL">Trend</th>
<th>9/27/2014</th>
<th>9/28/2013</th>
<th>9/29/2012</th>
<th>9/24/2011</th>
</tr>
</thead>
<tr>
<th bgcolor="#E6E6E6">Total Revenue</th>
<td class="td_genTable"><table border="0" align="center" width="*" cellspacing="0" cellpadding="0"><tr><td align="bottom"><table border="0" height="100%" cellspacing="0" cellpadding="0"><tr><td><table cellspacing="0" cellpadding="0" border="0"><tr><td height="15" bgcolor="#47C3D3" width="6"></td><td height="15" bgcolor="#FFFFFF" width="1px"></td></tr><tr><td height="1" colspan="2" bgcolor="#D1D1D1"></td></tr></table></td><td><table cellspacing="0" cellpadding="0" border="0"><tr><td height="1" bgcolor="#FFFFFF" width="6"></td><td height="1" bgcolor="#FFFFFF" width="1px"></td></tr><tr><td height="14" bgcolor="#47C3D3" width="6"></td><td height="14" bgcolor="#FFFFFF" width="1px"></td></tr><tr><td height="1" colspan="2" bgcolor="#D1D1D1"></td></tr></table></td><td><table cellspacing="0" cellpadding="0" border="0"><tr><td height="2" bgcolor="#FFFFFF" width="6"></td><td height="2" bgcolor="#FFFFFF" width="1px"></td></tr><tr><td height="13" bgcolor="#47C3D3" width="6"></td><td height="13" bgcolor="#FFFFFF" width="1px"></td></tr><tr><td height="1" colspan="2" bgcolor="#D1D1D1"></td></tr></table></td><td><table cellspacing="0" cellpadding="0" border="0"><tr><td height="7" bgcolor="#FFFFFF" width="6"></td><td height="7" bgcolor="#FFFFFF" width="1px"></td></tr><tr><td height="8" bgcolor="#47C3D3" width="6"></td><td height="8" bgcolor="#FFFFFF" width="1px"></td></tr><tr><td height="1" colspan="1" bgcolor="#D1D1D1"></td></tr></table></td></tr></table></td></tr></table></td>
<td>$182,795,000</td>
<td>$170,910,000</td>
<td>$156,508,000</td>
<td>$108,249,000</td>
    rows = table.findAll('tr')

    for row in rows:
        cols = row.findAll('td')
        col1 = [ele.text.strip().replace(',','') for ele in cols]

        account = col1[0:1]
        period1 = col1[2:3]
        period2 = col1[3:4]
        period3 = col1[4:5]

        record = (stock, account,period1,period3,period3)
        print record

【问题讨论】:

  • 您的第一个非标题行的第一列包含一个充满空单元格的表格,其中没有任何文本。您的代码正确地发现没有文本。我不确定你想让它做什么。
  • 同时,您为什么使用已弃用的名称findAll?您是从为 BS3 编写的示例代码中学习,而不是从 BS4 的更新示例或文档中学习吗?
  • 最后,find_all(或findAll)搜索所有后代,而不仅仅是顶级子代。因此,除非您想遍历外部表的行和嵌入在该表列中的每个子表的行并将它们视为相同,否则您不应该在这里使用它。

标签: python html beautifulsoup


【解决方案1】:

补充@abarnert 指出的内容。我会得到所有td 元素,其文本以$ 开头:

for row in soup.table.find_all('tr', recursive=False):
    record = [td.text.replace(",", "") for td in row.find_all("td", text=lambda x: x and x.startswith("$"))]
    print record

对于您提供的输入,它会打印:

[u'$182795000', u'$170910000', u'$156508000', u'$108249000']

您可以将其“解包”到单独的变量中:

account, period1, period2, period3 = record

请注意,我明确传递了 recursive=False 以避免在树中更深,并且只获得 table 元素的直接 tr 子元素。

【讨论】:

    【解决方案2】:

    您的第一个问题是find_all(或findAll,这只是同一事物的已弃用同义词)不只是在表中找到行,它在表中找到行并且在其中的每个子表中。您几乎肯定不想遍历这两种行并在每一行上运行相同的代码。如果您不希望这样,正如 the recursive argument 文档所说,请通过 recursive=False

    所以,现在您只能返回一排。如果你这样做row.find_all('td'),那将再次出现同样的问题——你将找到这一行的所有列,以及其中一个列中每个子表中每一行的所有列。同样,这不是你想要的,所以使用recursive=False

    现在您只返回 5 列。第一个只是一张大桌子,里面有一堆空单元格;另一方面,其他的则包含美元值,这似乎是您想要的。


    所以,只需将recursive=False 添加到两个调用中,并将stock 设置为某些东西(我不知道它应该从你的代码中来自哪里,但没有它你显然只会得到一个@ 987654331@):

    stock = 'spam'
    
    rows = table.find_all('tr', recursive=False)
    
    for row in rows:
        cols = row.findAll('td', recursive=False)
        col1 = [ele.text.strip().replace(',','') for ele in cols]
    
        account = col1[0:1]
        period1 = col1[2:3]
        period2 = col1[3:4]
        period3 = col1[4:5]
    
        record = (stock, account,period1,period3,period3)
    
        print record
    

    这将打印:

    ('spam', [''], ['$170910000'], ['$108249000'], ['$108249000'])
    

    我不确定您为什么使用了两次 period3 而从未使用过 period2,为什么您完全跳过了第 1 列,或者为什么您切片 1 元素列表而不只是索引值,但无论如何,这似乎成为你想要做的事情。


    作为旁注,如果您真的想将列表分成 5 个值,而不是跳过其中一个值的 4 个 1 元素列表,您可以这样写:

    account, whatever, period1, period2, period3 = col
    

    【讨论】:

    • @alecxe:要写书,您必须能够编辑内容。我的第 1 章将有 1300 页。 (这可能适用于小说,但 Tristam Shandy 早在 250 年前就已经写好了……)
    • 这行得通!谢谢你。你说的对。我使用股票作为变量来循环多个股票。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2013-06-16
    • 2013-01-29
    • 1970-01-01
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多