用rowspan和colspan解析表

发布于 2021-01-29 17:23:25

我有一个表需要解析,特别是这是一个学校时间表,有4个时间段,每个星期5天。我已经尝试解析它,但是说实话,它还没有走得太远,因为我坚持如何处理rowspan和colspan属性,因为它们本质上意味着缺少我需要继续的数据。

作为我想做的事的一个例子,这是一张桌子:

<tr>
    <td colspan="2" rowspan="4">#1</td>
    <td rowspan="4">#2</td>
    <td rowspan="2">#3</td>
    <td rowspan="2">#4</td>
</tr>

<tr>
</tr>

<tr>
    <td rowspan="2">#5</td>
    <td rowspan="2">#6</td>
</tr>

<tr>
</tr>

我要使用该表并将其转换为以下列表:

[[1,1,2,3,4],
 [1,1,2,3,4],
 [1,1,2,5,6],
 [1,1,2,5,6]]

现在,我得到一个清单,类似于:

[1,2,3,4,5,6]

但是以字典的形式,包含有关它跨越多少列和行的信息,描述以及它所在的星期。

显然,这需要适用于所有行跨度/列跨度以及在同一表中的多个星期。

html不像我描述的那么干净,我遗漏了很多属性,文本显然不像1,2,3,4那样干净,而是描述性文本块。但是,如果我可以解决这一部分,那么它应该足够容易地整合到我已经编写的内容中。

我一直在使用lxml.html和Python来做到这一点,但是如果它提供了更简单的解决方案,我愿意使用其他模块。

我希望有人可以帮助我,因为我真的不知道该怎么办。

编辑:

<table>
    <tr>
        <td> </td>
        <td> </td>
        <td> </td>
        <td rowspan="4">Thing</td>
        <td> </td>
    </tr>
    <tr>
        <td> </td>
        <td> </td>
        <td> </td>
        <td> </td>
    </tr>
    <tr>
        <td> </td>
        <td> </td>
        <td> </td>
        <td> </td>
    </tr>
    <tr>
        <td> </td>
        <td> </td>
        <td> </td>
        <td> </td>
    </tr>
</table>

这给我造成了一些问题,这正在输出

[' ', ' ', ' ', 'Thing', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ']

使用reclosedev提供的代码,我需要更改以适应它,以便输出

[' ', ' ', ' ', 'Thing', ' ']
[' ', ' ', ' ', 'Thing', ' ']
[' ', ' ', ' ', 'Thing', ' ']
[' ', ' ', ' ', 'Thing', ' ']

代替?

EDIT2:使用reclosedev的新功能,它正在解决一个问题,但是在某些情况下,它无法正确放置单元格:

<table> 
    <tr>
        <td> </td>
        <td rowspan="2"> DMAT Aud. 6 </td>
        <td rowspan="4"> Exam</td>
        <td rowspan="2"> DMAT Aud. 7</td>
        <td> </td>
    </tr>
    <tr>
        <td> </td>
        <td rowspan="2"> CART Aud. 4</td>
    </tr>
    <tr>
        <td> </td>
        <td rowspan="2"> CART Aud. 4</td>
        <td rowspan="2"> OOP Aud. 7</td>
    </tr>
    <tr>
        <td> </td>
        <td> </td>
    </tr>
</table>

这样,原始表将如下所示:

[
[' ', ' DMAT Aud. 6 ', ' Exam', ' DMAT Aud. 7', ' '],
[' ', ' DMAT Aud. 6 ', ' Exam', ' DMAT Aud. 7', ' CART Aud. 4'],
[' ', ' CART Aud. 4' , ' Exam', ' OOP Aud. 7' , ' CART Aud. 4'],
[' ', ' CART Aud. 4' , ' Exam', ' OOP Aud. 7' , ' ']
]

但是新的调用输出如下:

[
[' ', ' DMAT Aud. 6 ', ' Exam', ' DMAT Aud. 7', ' '],
[' ', ' DMAT Aud. 6 ', ' Exam', ' DMAT Aud. 7', ' CART Aud. 4'],
[' ', ' CART Aud. 4' , ' Exam', ' CART Aud. 4', ' OOP Aud. 7'],
[' ', ' CART Aud. 4' , ' Exam', ' OOP Aud. 7' , ' ']
]
关注者
0
被浏览
39
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    UPDATE (删除了先前的功能)

    UPDATE2已 修复和简化。

    我的第一个功能是错误的。这是另一个,它正在工作,但需要测试:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    from collections import defaultdict
    
    
    def table_to_list(table):
        dct = table_to_2d_dict(table)
        return list(iter_2d_dict(dct))
    
    
    def table_to_2d_dict(table):
        result = defaultdict(lambda : defaultdict(unicode))
        for row_i, row in enumerate(table.xpath('./tr')):
            for col_i, col in enumerate(row.xpath('./td|./th')):
                colspan = int(col.get('colspan', 1))
                rowspan = int(col.get('rowspan', 1))
                col_data = col.text_content()
                while row_i in result and col_i in result[row_i]:
                    col_i += 1
                for i in range(row_i, row_i + rowspan):
                    for j in range(col_i, col_i + colspan):
                        result[i][j] = col_data
        return result
    
    
    def iter_2d_dict(dct):
        for i, row in sorted(dct.items()):
            cols = []
            for j, col in sorted(row.items()):
                cols.append(col)
            yield cols
    
    
    if __name__ == '__main__':
        import lxml.html
        from pprint import pprint
    
        doc = lxml.html.parse('tables.html')
        for table_el in doc.xpath('//table'):
            table = table_to_list(table_el)
            pprint(table)
    

    table.html

    <table border="1">
        <tr>
            <td>1 </td>
            <td>1 </td>
            <td>1 </td>
            <td rowspan="4">Thing</td>
            <td>1 </td>
        </tr>
        <tr>
            <td>2 </td>
            <td>2 </td>
            <td>2 </td>
            <td>2 </td>
        </tr>
        <tr>
            <td>3 </td>
            <td>3 </td>
            <td>3 </td>
            <td>3 </td>
        </tr>
        <tr>
            <td>4 </td>
            <td>4 </td>
            <td>4 </td>
            <td>4 </td>
        </tr>
    </table>
    
    <table border="1">
    <tr>
        <td colspan="2" rowspan="4">#1</td>
        <td rowspan="4">#2</td>
        <td rowspan="2">#3</td>
        <td rowspan="2">#4</td>
    </tr>
    <tr></tr>
    <tr>
        <td rowspan="2">#5</td>
        <td rowspan="2">#6</td>
    </tr>
    <tr></tr>
    </table>
    

    输出:

    [['1 ', '1 ', '1 ', 'Thing', '1 '],
     ['2 ', '2 ', '2 ', 'Thing', '2 '],
     ['3 ', '3 ', '3 ', 'Thing', '3 '],
     ['4 ', '4 ', '4 ', 'Thing', '4 ']]
    [['#1', '#1', '#2', '#3', '#4'],
     ['#1', '#1', '#2', '#3', '#4'],
     ['#1', '#1', '#2', '#5', '#6'],
     ['#1', '#1', '#2', '#5', '#6']]
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看