如何在网页爬虫中正确提取超链接并避免 NaN 值

2次阅读

如何在网页爬虫中正确提取超链接并避免 NaN 值

本文详解在使用 beautifulsoup 爬取 EliteProspects 球员统计表格时,为何 Player_URL 列持续返回 NaN,并提供可复用的修复方案:定位嵌套 标签、预清洗字段、安全匹配名称,确保链接准确注入 DataFrame。

本文详解在使用 beautifulsoup 爬取 eliteprospects 球员统计表格时,为何 `player_url` 列持续返回 nan,并提供可复用的修复方案:定位嵌套 `eliteprospects nhl 2023–2024 统计页 为例,许多开发者尝试通过 提取球员个人主页链接,却始终得到 nan —— 根本原因在于: 元素自身不含 href 属性,真正的链接藏在其内部的 标签中

以下是一个精简、健壮且可直接运行的修复版本(基于原代码优化):

import requests from bs4 import BeautifulSoup import pandas as pd  start_url = 'https://www.php.cn/link/8641afa4db7421c9eeaf01260d8afefe' r = requests.get(start_url, timeout=10) r.raise_for_status()  # 显式检查 HTTP 错误  soup = BeautifulSoup(r.content, "html.parser") table = soup.find("table", class_="table table-striped table-sortable player-stats highlight-stats season")  # 提取表头(自动去重 & 清洗) headers = [th.get_text(strip=True) for th in table.find_all("th")] df = pd.DataFrame(columns=headers)  # 构建基础数据行(跳过表头行) for row in table.find_all("tr")[1:]:     cells = row.find_all(["td", "th"])     if len(cells) < len(headers):  # 跳过无效行(如分组标题)         continue     row_data = [cell.get_text(strip=True).replace('n', ' ') for cell in cells]     df.loc[len(df)] = row_data  # ✅ 关键修复:正确提取 Player_URL df["Player_URL"] = None  # 显式初始化列,避免 SettingWithCopyWarning  for span in table.find_all("span", class_="txt-blue"):     a_tag = span.find("a")     if not a_tag or not a_tag.get("href") or not a_tag.get_text(strip=True):         continue     player_name = a_tag.get_text(strip=True)     player_url = a_tag["href"]      # 安全匹配:df.Player 可能含括号/空格等干扰,需统一清洗     cleaned_names = df["Player"].str.strip().str.replace(r's+', ' ', regex=True)     match_mask = cleaned_names == player_name      if match_mask.any():         df.loc[match_mask, "Player_URL"] = player_url  # 后处理:全局清洗(推荐在填充 URL 后执行,避免干扰字符串匹配) df = df.replace(r's+', ' ', regex=True).applymap(     lambda x: x.strip() if isinstance(x, str) else x )  print(df[["Player", "Team", "GP", "G", "A", "TP", "Player_URL"]].head())

⚠️ 关键注意事项与最佳实践

  • 不要直接操作 span.get(“href”):HTML 中 John Doe 是典型嵌套结构,href 属于 ,而非
  • 名称匹配前必须清洗:原始 Player 列常含换行符(n)、多余空格或括号(如 “Connor McDavid (C)”),而链接文本通常为 “Connor McDavid”。务必在 df.Player == name 前对双方做 strip() 和正则清理。
  • 避免未定义变量:原代码中 name 未声明即使用,属运行时错误;应从 a_tag.text 动态提取。
  • 防御性编程不可少:添加 if not a_tag: 检查、r.raise_for_status() 和 timeout,防止因网络波动或 dom 变更导致脚本静默失败。
  • 列初始化显式化:使用 df[“Player_URL”] = None 而非依赖 .loc[] 自动创建,提升可读性与稳定性。

? 扩展提示:若需批量爬取多赛季(2007–2023)或多联赛,建议将上述逻辑封装为函数 scrape_season(league, season),配合 time.sleep(1) 遵守 robots.txt,并用 requests.session() 复用连接提升效率。球员身高体重等深层字段,则需对 Player_URL 发起二次请求,在个人页中解析对应

/
结构——此时同样适用本教程的核心原则:逐层定位标签、清洗再匹配、异常必兜底

通过理解 HTML 结构本质而非盲目套用选择器,你不仅能解决当前的 NaN 问题,更能构建出鲁棒、可维护的爬虫管线。

text=ZqhQzanResources