【问题标题】:Parse HTML table to Python list?将 HTML 表解析为 Python 列表?
【发布时间】:2011-09-13 14:10:09
【问题描述】:

我想获取一个 HTML 表格并对其进行解析以获取字典列表。每个列表元素都是一个字典,对应于表中的一行。

例如,如果我有一个包含三列(由标题标签标记)、“事件”、“开始日期”和“结束日期”的 HTML 表,并且该表有 5 个条目,我想解析该表返回一个长度为 5 的列表,其中每个元素都是一个带有键“事件”、“开始日期”和“结束日期”的字典。

感谢您的帮助!

【问题讨论】:

    标签: python html


    【解决方案1】:

    Sven Marnach excellent solution 可直接翻译成 ElementTree,这是最近 Python 发行版的一部分:

    from xml.etree import ElementTree as ET
    
    s = """<table>
      <tr><th>Event</th><th>Start Date</th><th>End Date</th></tr>
      <tr><td>a</td><td>b</td><td>c</td></tr>
      <tr><td>d</td><td>e</td><td>f</td></tr>
      <tr><td>g</td><td>h</td><td>i</td></tr>
    </table>
    """
    
    table = ET.XML(s)
    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)))
    

    与 Sven Marnach 的答案相同的输出...

    【讨论】:

    • +1 因为它允许使用 cElementTree 而不是 ElementTree,如果涉及大量表,它比 lxml 快得多
    • 我有一个从维基百科保存的网页。如何向 ET 指定要解析和获取数据的表?是否可以通过表名或表ID?
    • 另外, 和 也不起作用。见stackoverflow.com/q/49286753/8929814
    【解决方案2】:

    解析 HTML 表格的最简单方法是使用 pandas.read_html() - 它同时接受 URL 和 HTML。

    import pandas as pd
    url = r'https://en.wikipedia.org/wiki/List_of_S%26P_500_companies'
    tables = pd.read_html(url) # Returns list of all tables on page
    sp500_table = tables[0] # Select table of interest
    

    唯一的缺点是read_html() 不保留超链接。

    【讨论】:

    • 太棒了!谢谢。
    • 谢谢!这是非常快速和容易的。
    • 对于包含 rowspancolspan 的表来说不是一个好方法!
    • @JohnStrood 期待阅读您关于如何处理rowspancolspan 的答案?
    • @tommy.carstensen 啊!我使用bs4 构建了一个元素树,并遍历元素以将跨行跨列单元格分解为组成单元格。
    【解决方案3】:

    您应该使用一些 HTML 解析库,例如 lxml:

    from lxml import etree
    s = """<table>
      <tr><th>Event</th><th>Start Date</th><th>End Date</th></tr>
      <tr><td>a</td><td>b</td><td>c</td></tr>
      <tr><td>d</td><td>e</td><td>f</td></tr>
      <tr><td>g</td><td>h</td><td>i</td></tr>
    </table>
    """
    table = etree.HTML(s).find("body/table")
    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))
    

    打印

    {'End Date': 'c', 'Start Date': 'b', 'Event': 'a'}
    {'End Date': 'f', 'Start Date': 'e', 'Event': 'd'}
    {'End Date': 'i', 'Start Date': 'h', 'Event': 'g'}
    

    【讨论】:

    • 我的表有不同数量的行。如果是这种情况,我怎样才能让它工作?感谢您的回复,顺便说一句。
    • @Andrew:上面的代码适用于任意数量的行和任意数量的列,只要每行的列数相同。
    • 我建议HTMLParser/html.parser,但在这种情况下这个解决方案要好得多。
    • 这是进一步研究的有用指针。我实际上有一些损坏的 HTML 需要解析,所以其他一些涉及 lxml.html 的答案也被证明是有用的。
    • 如果 html 包含未加引号的属性,例如 ",它会失败
    【解决方案4】:

    如果 HTML 不是 XML,您无法使用 etree。但即便如此,您也不必使用外部库来解析 HTML 表格。在 python 3 中,您可以使用来自html.parserHTMLParser 来实现您的目标。我有简单派生的 HTMLParser 类 here in a github repo 的代码。

    您可以通过以下方式使用该类(此处命名为HTMLTableParser):

    import urllib.request
    from html_table_parser import HTMLTableParser
    
    target = 'http://www.twitter.com'
    
    # get website content
    req = urllib.request.Request(url=target)
    f = urllib.request.urlopen(req)
    xhtml = f.read().decode('utf-8')
    
    # instantiate the parser and feed it
    p = HTMLTableParser()
    p.feed(xhtml)
    print(p.tables)
    

    它的输出是代表表格的二维列表。它看起来可能是这样的:

    [[['   ', ' Anmelden ']],
     [['Land', 'Code', 'Für Kunden von'],
      ['Vereinigte Staaten', '40404', '(beliebig)'],
      ['Kanada', '21212', '(beliebig)'],
      ...
      ['3424486444', 'Vodafone'],
      ['  Zeige SMS-Kurzwahlen für andere Länder ']]]
    

    【讨论】:

    • 很棒的解析器!!
    • 确实很整洁。如果某些 td 有 colspan ,它会中断
    猜你喜欢
    • 2013-08-03
    • 2016-09-03
    • 1970-01-01
    • 2016-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多