如何使用BeautifulSoup获取列索引号码?

1 投票
1 回答
846 浏览
提问于 2025-04-11 09:35

大约一周前,我遇到了一个问题。因为我觉得解决这个问题的方法挺有意思的,所以在等待我之前提问的答案时,我想把它分享出来。我需要知道表格中列标题的相对位置,这样我才能把列标题和下面的数据行对应起来。我发现我的一些表格的第一行是这样的:

<!-- Table Width Row -->
<TR style="font-size: 1pt" valign="bottom">
<TD width="60%">&nbsp;</TD> <!-- colindex=01 type=maindata -->
<TD width="1%">&nbsp;</TD>  <!-- colindex=02 type=gutter -->
<TD width="1%" align="right">&nbsp;</TD>    <!-- colindex=02 type=lead -->
<TD width="9%" align="right">&nbsp;</TD>    <!-- colindex=02 type=body -->
<TD width="1%" align="left">&nbsp;</TD> <!-- colindex=02 type=hang1 -->

<TD width="3%">&nbsp;</TD>  <!-- colindex=03 type=gutter -->
<TD width="1%" align="right">&nbsp;</TD>    <!-- colindex=03 type=lead -->
<TD width="4%" align="right">&nbsp;</TD>    <!-- colindex=03 type=body -->
<TD width="1%" align="left">&nbsp;</TD> <!-- colindex=03 type=hang1 -->
<TD width="3%">&nbsp;</TD>  <!-- colindex=04 type=gutter -->
<TD width="1%" align="right">&nbsp;</TD>    <!-- colindex=04 type=lead -->

<TD width="4%" align="right">&nbsp;</TD>    <!-- colindex=04 type=body -->
<TD width="1%" align="left">&nbsp;</TD> <!-- colindex=04 type=hang1 -->
<TD width="3%">&nbsp;</TD>  <!-- colindex=05 type=gutter -->
<TD width="1%" align="right">&nbsp;</TD>    <!-- colindex=05 type=lead -->
<TD width="5%" align="right">&nbsp;</TD>    <!-- colindex=05 type=body -->
<TD width="1%" align="left">&nbsp;</TD> <!-- colindex=05 type=hang1 -->

 </TR>

我当时想,太简单了,因为数据在下面的列中,类型是body。往下数,我知道在数据行中,我需要获取第[3, 7, 11, 15]列的值。所以我开始用这段代码来实现:

indexComment = souptoGetColIndex.findAll(text=re.compile("type=body"))
indexRow=indexComment[0].findParent()
indexCells=indexRow.findAll(text=re.compile("type=body"))
for each in range(len(indexCells)):
    collist.append(tdlist.index(indexCells[each].previousSibling.previousSibling))

结果我得到了一个列表,内容是 collist=[0, 3, 7, 7, 15]

后来我发现,因为第7和第11个位置的单元格看起来一模一样,所以返回了相同的索引位置。我在想该怎么处理这个问题,显然我得让它们看起来不一样。于是我做了一个操作,先用readlines读取文件的每一行,然后把空白的地方换成随机整数。

for each in toGetColIndex:
   newlt.append(each.replace(r"&nbsp;",str(random.randint(1,14567))))

一个朋友提醒我,可以用这个方法来减少开销:

for each in toGetColIndex:
   newlt.append(each.replace(r"&nbsp;",str(toGetColIndex.index(each))))

不过,这些方法都能让我得到一个列表,里面是每一列标题的位置索引,可以用在数据行上。需要注意的是,replace函数没有处理空白,因为我猜是html导致它消失了,实际上代码使用的是r"&.n.b.s.p;",中间没有点。

1 个回答

1

下面的代码会生成 [3, 7, 11, 15],这就是我理解你想要的结果。

from BeautifulSoup import BeautifulSoup
from re import compile

soup = BeautifulSoup(
    '''<HTML><BODY>
    <TABLE>
    <TR style="font-size: 1pt" valign="bottom">
    <TD width="60%"> </TD> <!-- colindex=01 type=maindata -->
    <TD width="1%"> </TD>  <!-- colindex=02 type=gutter -->
    <TD width="1%" align="right"> </TD>    <!-- colindex=02 type=lead -->
    <TD width="9%" align="right"> </TD>    <!-- colindex=02 type=body -->
    <TD width="1%" align="left"> </TD> <!-- colindex=02 type=hang1 -->

    <TD width="3%"> </TD>  <!-- colindex=03 type=gutter -->
    <TD width="1%" align="right"> </TD>    <!-- colindex=03 type=lead -->
    <TD width="4%" align="right"> </TD>    <!-- colindex=03 type=body -->
    <TD width="1%" align="left"> </TD> <!-- colindex=03 type=hang1 -->
    <TD width="3%"> </TD>  <!-- colindex=04 type=gutter -->
    <TD width="1%" align="right"> </TD>    <!-- colindex=04 type=lead -->

    <TD width="4%" align="right"> </TD>    <!-- colindex=04 type=body -->
    <TD width="1%" align="left"> </TD> <!-- colindex=04 type=hang1 -->
    <TD width="3%"> </TD>  <!-- colindex=05 type=gutter -->
    <TD width="1%" align="right"> </TD>    <!-- colindex=05 type=lead -->
    <TD width="5%" align="right"> </TD>    <!-- colindex=05 type=body -->
    <TD width="1%" align="left"> </TD> <!-- colindex=05 type=hang1 -->

     </TR>
    </TABLE> </BODY></HTML>'''
)

tables = soup.findAll('table')
matcher = compile('colindex')

def body_cols(row):
    for i, comment in enumerate(row.findAll(text=matcher)):
        if 'type=body' in comment:
            yield i

for table in soup.findAll('table'):
    index_row = table.find('tr')
    print list(body_cols(index_row))

撰写回答