使用BeautifulSoup 4解析排班表:关联班次时间与日期的问题
排班表解析问题:班次时间与日期关联失败
问题背景
我正在编写自动化脚本,用于登录公司排班软件,解析排班表数据并打印本周所有排班班次。目前已成功提取班次时间,但无法将其与对应日期关联,尝试ChatGPT协助仍未解决问题,现寻求技术帮助。
排班表HTML结构
<table class="sc-bTmccw sc-laFCIP sc-ctuRtO ibflim hoCFsG gsXXhe"> <thead> <tr> <th class="sc-ccJWcV pRLto">America/Chicago</th> <th class="sc-gZVZiL kofAkN"> <div class="sc-bgnbwU cSZwXw">Monday</div> <div class="sc-bgnbwU cSZwXw">Sep 25, 2023</div> </th> <th class="sc-gZVZiL kofAkN"> <div class="sc-bgnbwU cSZwXw">Tuesday</div> <div class="sc-bgnbwU cSZwXw">Sep 26, 2023</div> </th> <th class="sc-gZVZiL kofAkN"> <div class="sc-bgnbwU cSZwXw">Wednesday</div> <div class="sc-bgnbwU cSZwXw">Sep 27, 2023</div> </th> <th class="sc-gZVZiL kofAkN"> <div class="sc-bgnbwU cSZwXw">Thursday</div> <div class="sc-bgnbwU cSZwXw">Sep 28, 2023</div> </th> <th class="sc-gZVZiL kofAkN"> <div class="sc-bgnbwU cSZwXw">Friday</div> <div class="sc-bgnbwU cSZwXw">Sep 29, 2023</div> </th> <th class="sc-gZVZiL kofAkN"> <div class="sc-bgnbwU cSZwXw">Saturday</div> <div class="sc-bgnbwU cSZwXw">Sep 30, 2023</div> </th> <th class="sc-gZVZiL kofAkN"> <div class="sc-bgnbwU cSZwXw">Sunday</div> <div class="sc-bgnbwU cSZwXw">Oct 1, 2023</div> </th> </tr> </thead> <tbody> <tr> <td class="sc-gVAlfg bWxTWJ"> <div class="sc-iRaSfU kkorew">12:00 AM</div> <div class="sc-iRaSfU kkorew">1:00 AM</div> <div class="sc-iRaSfU kkorew">2:00 AM</div> <div class="sc-iRaSfU kkorew">3:00 AM</div> <div class="sc-iRaSfU kkorew">4:00 AM</div> <div class="sc-iRaSfU kkorew">5:00 AM</div> <div class="sc-iRaSfU kkorew">6:00 AM</div> <div class="sc-iRaSfU kkorew">7:00 AM</div> <div class="sc-iRaSfU kkorew">8:00 AM</div> <div class="sc-iRaSfU kkorew">9:00 AM</div> <div class="sc-iRaSfU kkorew">10:00 AM</div> <div class="sc-iRaSfU kkorew">11:00 AM</div> <div class="sc-iRaSfU kkorew">12:00 PM</div> <div class="sc-iRaSfU kkorew">1:00 PM</div> <div class="sc-iRaSfU kkorew">2:00 PM</div> <div class="sc-iRaSfU kkorew">3:00 PM</div> <div class="sc-iRaSfU kkorew">4:00 PM</div> <div class="sc-iRaSfU kkorew">5:00 PM</div> <div class="sc-iRaSfU kkorew">6:00 PM</div> <div class="sc-iRaSfU kkorew">7:00 PM</div> <div class="sc-iRaSfU kkorew">8:00 PM</div> <div class="sc-iRaSfU kkorew">9:00 PM</div> <div class="sc-iRaSfU kkorew">10:00 PM</div> <div class="sc-iRaSfU kkorew">11:00 PM</div> </td> <td class="sc-gVAlfg sc-bRDiDf bWxTWJ hISnGZ"></td> <td class="sc-gVAlfg sc-bRDiDf bWxTWJ hISnGZ"> <a class="sc-qxRCG sc-gBMFIu iTTzGz ifHVoI" style="height: 325px; transform: translateY(775px);"> <span class="sc-cQAbrN bHxBCY"> <h4 class="sc-gdnLxT sc-dMxQAh fbZdSM tkxgA">Coverage</h4> <span class="sc-jRztuO sc-hAJyxc bGJrvP hdkZRS"><time>3:30 PM - 10:00 PM</time></span> <aside></aside> </span> </a> </td> <td class="sc-gVAlfg sc-bRDiDf bWxTWJ hISnGZ"></td> <td class="sc-gVAlfg sc-bRDiDf bWxTWJ hISnGZ"> <a class="sc-qxRCG sc-gBMFIu iTTzGz ifHVoI" style="height: 350px; transform: translateY(750px);"> <span class="sc-cQAbrN bHxBCY"> <h4 class="sc-gdnLxT sc-dMxQAh fbZdSM tkxgA">Keyholder</h4> <span class="sc-jRztuO sc-hAJyxc bGJrvP hdkZRS"><time>3:00 PM - 10:00 PM</time></span> <aside></aside> </span> </a> </td> <td class="sc-gVAlfg sc-bRDiDf bWxTWJ hJzsUD"> <a class="sc-qxRCG sc-gBMFIu iTTzGz ifHVoI" style="height: 225px; transform: translateY(900px);"> <span class="sc-cQAbrN bHxBCY"> <h4 class="sc-gdnLxT sc-dMxQAh fbZdSM tkxgA">Coverage</h4> <span class="sc-jRztuO sc-hAJyxc bGJrvP hdkZRS"><time>6:00 PM - 10:30 PM</time></span> <aside></aside> </span> </a> </td> <td class="sc-gVAlfg sc-bRDiDf bWxTWJ hISnGZ"> <a class="sc-qxRCG sc-gBMFIu iTTzGz ifHVoI" style="height: 350px; transform: translateY(500px);"> <span class="sc-cQAbrN bHxBCY"> <h4 class="sc-gdnLxT sc-dMxQAh fbZdSM tkxgA">Coverage</h4> <span class="sc-jRztuO sc-hAJyxc bGJrvP hdkZRS"><time>10:00 AM - 5:00 PM</time></span> <aside></aside> </span> </a> </td> <td class="sc-gVAlfg sc-bRDiDf bWxTWJ hISnGZ"> <a class="sc-qxRCG sc-gBMFIu iTTzGz ifHVoI" style="height: 325px; transform: translateY(250px);"> <span class="sc-cQAbrN bHxBCY"> <h4 class="sc-gdnLxT sc-dMxQAh fbZdSM tkxgA">Keyholder</h4> <span class="sc-jRztuO sc-hAJyxc bGJrvP hdkZRS"><time>5:00 AM - 11:30 AM</time></span> <aside></aside> </span> </a> </td> </tr> </tbody> </table>
当前BeautifulSoup解析代码
soup = BeautifulSoup(browser.page_source, 'html.parser') # Find the table headers table_headers = soup.find_all('th', class_='sc-gZVZiL kofAkN') # Initialize a dictionary to store the data data = {} # Extract column headers (dates) from the table headers column_headers = [header.find('div', class_='sc-bgnbwU cSZwXw').text.strip() for header in table_headers] # Find the rows rows = soup.find_all('tr') # Initialize variables to store date and time current_date = "" current_time_ranges = [] # Extract the data from the rows for row in rows: cells = row.find_all('td') if cells: # Check if the cell contains coverage information coverage_cell = cells[1].find('span', class_='sc-cNAXLz bGJrvP PQKTa') if coverage_cell: # Extract the time range from the coverage cell time_range = coverage_cell.find('time').text.strip() current_time_ranges.append(time_range) else: # If the cell doesn't contain coverage information, use an empty string for the time range time_range = "" # Extract the data for the remaining cells data_row = [column_headers[1]] + current_time_ranges + [info.text.strip() for info in cells[2:]] # Store the data in the dictionary data[row] = data_row # Print the extracted data for key, value in data.items(): print(key) for item in value: print(item)
当前输出
Coverage - 3:30 PM - 10:00 PM Keyholder - 3:00 PM - 10:00 PM Coverage - 6:00 PM - 10:30 PM Coverage - 10:00 AM - 5:00 PM Keyholder - 5:00 AM - 11:30 AM
期望输出
Tue 3:30 PM - 10:00 PM Thu 3:00 PM - 10:00 PM Fri 6:00 PM - 10:30 PM Sat 10:00 AM - 5:00 PM Sun 5:00 AM - 11:30 AM
解决方案
原代码存在两个核心问题:一是仅检查周一的单元格(cells[1]),未遍历所有日期列;二是班次元素的类名匹配错误。以下是修正后的代码:
from bs4 import BeautifulSoup soup = BeautifulSoup(browser.page_source, 'html.parser') # 提取表头中的星期缩写(如Tue、Thu) day_headers = soup.find_all('th', class_='sc-gZVZiL kofAkN') day_short_names = [header.find_all('div')[0].text.strip()[:3] for header in day_headers] # 获取排班数据行及所有日期对应的单元格(跳过左侧时间列) schedule_row = soup.find('tbody').find('tr') day_cells = schedule_row.find_all('td')[1:] # 遍历每个日期单元格,匹配并输出班次信息 for idx, cell in enumerate(day_cells): shift_element = cell.find('span', class_='sc-jRztuO sc-hAJyxc bGJrvP hdkZRS') if shift_element: time_range = shift_element.find('time').text.strip() print(f"{day_short_names[idx]} {time_range}")
修正说明
- 日期与单元格对齐:通过索引对应表头的星期缩写和tbody中的日期单元格,确保班次与日期一一匹配。
- 遍历所有日期列:不再局限于单个单元格,遍历所有日期列查找班次。
- 修正类名匹配:使用HTML中实际存在的班次元素类名,确保能正确提取时间信息。
内容的提问来源于stack exchange,提问作者Dayton
相关产品推荐
相关产品推荐

