Python3-如何提取行标记<tr>中的所有元素并将其作为行附加到数据框?

时间:2019-11-07 20:35:22

标签: python html pandas dataframe beautifulsoup

我正在尝试从html表中提取行,并将它们附加到DataFrame或直接添加到Excel电子表格中。

我想保留表的原始结构,因为它映射了矩阵系统的物理布局。例如,我尝试提取的数据就是这种形式。

<div id="FA_DSC"><p>Table_Title</p><table border="1" cellpadding="4"style="border: 1px solid #000000; border-collapse: collapse;">
<tr>
<td> </td>
<td> </td>
<td>X68</td>
<td>X20</td>
<td>X17</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td>X80</td>
<td>X84</td>
<td>V28</td>
<td>X02</td>
<td>X12</td>
<td> </td>
</tr>
<tr>
<td>X22</td>
<td>X55</td>
<td>V57</td>
<td>U15</td>
<td>V29</td>
<td>X51</td>
<td>X40</td>
</tr>
</table></div>

我想取一个并将其插入Excel工作表/数据框,以便它可以遵循这种格式,

            Table_Title             
            X68 X20 X17     
        X80 X84 V28 X02 X12 
    X22 X55 V57 U15 V29 X51 X40

使用BeautifulSoup,我可以使用以下内容找到我要提取的所有表

with open(r'D:\yolo\frolo\dolo.html','r') as f:
    contents = f.read()
    soup = BeautifulSoup(contents.encode("UTF8"),'lxml')
    table = soup.find_all('div',{'id':'table'})

从这里开始,我试图提取之间的所有内容,但是我不知道在保持行的完整性的同时这样做的方法。

例如,我尝试过

for i in table:
    for k in i:
        text = i.get_text().split('\n')
        print(text)

但是会返回这样的迭代。

['Table_Title']
['', '', ' ', ' ', 'X68', 'X20', 'X17', ' ', ' ', 
'', '', ' ', 'X80', 'X84', 'V28', 'X02', 'X12', ' ', 
'', '', 'X22', 'X55', 'V57', 'U15', 'V29', 'X51', 'X40',
'', '', 'X14', 'W05', 'T34', 'U36', 'T38', 'S75', 'X24', 
'', '', 'X83', 'X57', 'U48', 'V10', 'T82', 'X04', 'X11',
'', '', ' ', 'X82', 'X59', 'T39', 'X03', 'X18', ' ', '',
'', ' ', ' ', 'X78', 'X15', 'X41', ' ', ' ', '', '']

我也尝试过

table.find_all('td')

返回哪个,

AttributeError: ResultSet object has no attribute 'find_all'. 
You're probably treating a list of items like a single item. 
Did you call find_all() when you meant to call find()?

我最近得到的就是使用列表获取数据

k.contents

当我尝试使用正则表达式时

print(re.findall("<tr>(.*?)</tr>", "".join(k.contents)))

我明白了

TypeError: sequence item 1: expected str instance, Tag found

总而言之,这是我的初始代码,我希望能从中获得一些指导。

with open(r'D:\yolo\frolo\dolo.html','r') as f:
    contents = f.read()
    soup = BeautifulSoup(contents.encode("UTF8"),'lxml')
    table = soup.find_all('div',{'id':'table'})

我是BeautifulSoup和html的新手,希望有人可以帮助提取这些行。 BeautifulSoup是否具有可用于逐行提取表的功能?

希望我对此进行了明确的沟通,对冗长的帖子表示歉意。只是试图为每个人提供足够的信息来帮助我解决问题。

2 个答案:

答案 0 :(得分:0)

这会将每个表的数据存储在其自己的列表中,并将该表下的每一行的数据存储在其自己的列表中:

from bs4 import BeautifulSoup
html = """
<div id="FA_DSC"><p>Table_Title</p><table border="1" cellpadding="4"style="border: 1px solid #000000; border-collapse: collapse;">
<tr>
<td> </td>
<td> </td>
<td>X68</td>
<td>X20</td>
<td>X17</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td>X80</td>
<td>X84</td>
<td>V28</td>
<td>X02</td>
<td>X12</td>
<td> </td>
</tr>
<tr>
<td>X22</td>
<td>X55</td>
<td>V57</td>
<td>U15</td>
<td>V29</td>
<td>X51</td>
<td>X40</td>
</tr>
</table></div>
"""

soup = BeautifulSoup(html, 'lxml')

data = []
for table in soup.select('table'):
    table_data = []
    data.append(table_data)
    for tr in table.select('tr'):
        row_data = []
        table_data.append(row_data)
        for td in tr.select('td'):
            row_data.append(td.get_text())

print(data)

输出

[[[' ', ' ', 'X68', 'X20', 'X17', ' ', ' '], [' ', 'X80', 'X84', 'V28', 'X02', 'X12', ' '], ['X22', 'X55', 'V57', 'U15', 'V29', 'X51', 'X40']]]

答案 1 :(得分:0)

您可以使用pandas.read_html

import pandas as pd

html="""<div id="FA_DSC"><p>Table_Title</p><table border="1" cellpadding="4"style="border: 1px solid #000000; border-collapse: collapse;">
<tr>
<td> </td>
<td> </td>
<td>X68</td>
<td>X20</td>
<td>X17</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td>X80</td>
<td>X84</td>
<td>V28</td>
<td>X02</td>
<td>X12</td>
<td> </td>
</tr>
<tr>
<td>X22</td>
<td>X55</td>
<td>V57</td>
<td>U15</td>
<td>V29</td>
<td>X51</td>
<td>X40</td>
</tr>
</table></div>"""
pd.read_html(html)

出局:

     0    1    2    3    4    5    6
0  NaN  NaN  X68  X20  X17  NaN  NaN
1  NaN  X80  X84  V28  X02  X12  NaN
2  X22  X55  V57  U15  V29  X51  X40