遍历HTML tbody生成DataFrame遇数据重复问题求助(NHL球队数据)
爬取NHL 2022-2023赛季球队数据时的数据重复问题排查
问题概述
爬取NHL 2022-2023赛季球队数据时,通过requests获取目标网页内容,使用BeautifulSoup解析HTML表格。表头提取逻辑正常,但遍历<tbody>生成数据行时出现数据重复,无法得到32条对应球队的有效数据。
目标网页结构(简化版)
<table> <colgroup> <col /> </colgroup> <thead> <tr> <th></th> </tr> </thead> <tbody> <tr> <td></td> </tr> </tbody> </table>
现有Python代码
import requests from bs4 import BeautifulSoup import pandas as pd ##### LOAD IN NHL TEAM STATS ###### # Send a GET request to the Natural Stat Trick website and retrieve the HTML content nhl_team_stats = "https://www.naturalstattrick.com/teamtable.php?fromseason=20222023&thruseason=20222023&stype=2&sit=all&score=all&rate=y&team=all&loc=B&gpf=410&fd=&td=" nhl_team_stats_response = requests.get(nhl_team_stats) nhl_team_stats_html_content = nhl_team_stats_response.content # Use BeautifulSoup to parse the HTML content nhl_team_stats_soup = BeautifulSoup(nhl_team_stats_html_content, "html.parser") # Find the table containing the NHL schedule data nhl_team_stats_table = nhl_team_stats_soup.find("table", attrs={"id": "teams"}) # Extract the table headers nhl_team_stats_headers = [] for thead in nhl_team_stats_table.find_all('thead'): for tr in thead.find_all("tr"): for th in tr.find_all("th"): nhl_team_stats_headers.append(th.text.strip()) nhl_team_stats_headers[0] = "ID" print(nhl_team_stats_headers) # Extract the table rows nhl_team_stats_rows = [] teams_list = [] tbody = nhl_team_stats_table.find("tbody") for tr in tbody.find_all("tr"): row = [] for td in tr.find_all(["td"]): cell_text = td.text.strip() row.append(cell_text) nhl_team_stats_rows.append(row) teams_list.append(row[1]) print(nhl_team_stats_rows) # print(teams_list) # Convert the nhl_team_stats_rows to a DataFrame # nhl_team_stats_df = pd.DataFrame(nhl_team_stats_rows, nhl_team_stats_headers) # Get the mean xGF/60 # mean_gf = pd.to_numeric(nhl_team_stats_df[22], errors='coerce').mean() # Convert the teams_list to a DataFrame # teams_df = pd.DataFrame(teams_list, columns=["Team"])
问题原因与解决方法
核心问题
目标网页的<tbody>中存在无效行(比如隐藏的响应式折叠行、汇总统计行),这些行被find_all("tr")一并抓取,导致数据重复或冗余。
解决方案
通过以下两种方式过滤无效行:
按单元格数量匹配过滤
只有当行的单元格数量与表头字段数量一致时,才视为有效球队数据行:# 修改后的行提取逻辑 nhl_team_stats_rows = [] teams_list = [] tbody = nhl_team_stats_table.find("tbody") header_count = len(nhl_team_stats_headers) for tr in tbody.find_all("tr"): tds = tr.find_all("td") # 只保留单元格数量与表头一致的行 if len(tds) == header_count: row = [td.text.strip() for td in tds] nhl_team_stats_rows.append(row) teams_list.append(row[1])按行的class属性过滤
查看网页实际HTML,无效行通常带有特定class(比如hidden),直接过滤这类行:# 修改后的行提取逻辑 nhl_team_stats_rows = [] teams_list = [] tbody = nhl_team_stats_table.find("tbody") for tr in tbody.find_all("tr", class_=lambda x: x != "hidden"): # 替换为实际无效行的class row = [td.text.strip() for td in tr.find_all("td")] nhl_team_stats_rows.append(row) teams_list.append(row[1])
验证结果
修改后重新运行代码,teams_list应包含32条唯一的球队名称,nhl_team_stats_rows也将对应32条有效数据行。
内容的提问来源于stack exchange,提问作者Tony Ingle
相关产品推荐
相关产品推荐

