python:将带有UNNESTED div标签的html文档解析为数据框(使用beautifulsoup)

问题描述 投票:0回答:1

长期用户,但从未问过我自己的问题。

我想使用 python 将 html 文档中的表格解析为数据框。该表不是一个 html 表,我认为它是 javascript 创建的 html,只是使用一堆带有奇怪命名类的 div 来创建格式和布局。

数据是工人及其工作时间,按工作区域排序。问题是,div 不是嵌套的,因此我无法轻松地为每个工作人员分配他们的工作区域。我用的是beautifulsoup。

这是一个简化的示例:

<html>
<body>
<div class="workarea">construction
</div>
  <div class="name">Anna
  </div>
  <div class="Muell">w23f84md2o
  </div>
  <div class="time">8:23
  </div>
    <div class="name">Tom
  </div>
  <div class="Muell">w23f84md2o
  </div>
  <div class="time">10:20
  </div>
 <div class="workarea">cleaning
</div>
  <div class="name">Max
  </div>
  <div class="Muell">w23f84md2o
  </div>
  <div class="time">9:30
  </div>
</body>
</html>

这是我想要的数据框:

工作区 姓名 时间
施工 安娜 8:23
施工 汤姆 10:20
清洁 最大 9:30

注意:真实数据有数千个用于格式化和布局的 div,这就是为什么我想使用合适的解析器,而不仅仅是将文档逐行读取到 python 中并自己解析。

我没有走多远:

### read html with bs4
with open("testdoc1.html") as fp:
     soup=BeautifulSoup(fp,"html.parser")

wa = soup.find_all("div",class="workarea")
## here I wanted to add a for loop through wa, but wa doesnt actually contain the info

我无法循环通过

wa
来获取详细信息,因为它只包含构造和清洁 div,中间没有任何内容。

有没有一种解决方案可以逐行解析,但实际上是逐格解析?

我可以让 find_all 找到所有具有类 工作区、时间或名称 的 div 吗?并保持它们的阅读顺序?

我知道 stackoverflow 上已经有很多关于 beautifulsoup 和解析 html 文档的问题,但我找不到真正的解决方案,因为原始表并不只是一张表,遗憾的是 html 中没有保留层次结构。

非常感谢您的帮助!非常感谢任何提示!

python html parsing beautifulsoup html-parsing
1个回答
0
投票

尝试:

import pandas as pd
from bs4 import BeautifulSoup

html_text = """\
<html>
<body>
<div class="workarea">construction
</div>
  <div class="name">Anna
  </div>
  <div class="Muell">w23f84md2o
  </div>
  <div class="time">8:23
  </div>
    <div class="name">Tom
  </div>
  <div class="Muell">w23f84md2o
  </div>
  <div class="time">10:20
  </div>
 <div class="workarea">cleaning
</div>
  <div class="name">Max
  </div>
  <div class="Muell">w23f84md2o
  </div>
  <div class="time">9:30
  </div>
</body>
</html>"""

soup = BeautifulSoup(html_text, "html.parser")

data = []
for name in soup.select(".name"):
    workarea = name.find_previous(class_="workarea")
    data.append(
        {
            "workarea": workarea.text.strip(),
            "name": name.text.strip(),
            "time": name.find_next(class_="time").text.strip(),
        }
    )

df = pd.DataFrame(data)
print(df)

打印:

       workarea  name   time
0  construction  Anna   8:23
1  construction   Tom  10:20
2      cleaning   Max   9:30
© www.soinside.com 2019 - 2024. All rights reserved.