如何安全提取Beautiful Soup中含链接的表格行数据

16次阅读

如何安全提取Beautiful Soup中含链接的表格行数据

本文详解在使用beautiful soup解析网页表格时,因部分表格行缺失 `big chart 页面 为例,#section-chemicals 表能成功遍历,而 #section-plants 表却抛出 Attributeerror: ‘nonetype’ Object has no attribute ‘contents’——根本原因在于:该表首行是表头(

)或空行,不含任何 标签,导致 r.find(‘a’) 返回 none,后续调用 .contents[0] 或 .text 必然失败。

直接对 find() 结果做属性访问而不校验,是引发此类错误的典型模式。以下是推荐的三种稳健处理方式:

✅ 方案一:使用 css 伪类 :has()(推荐,简洁高效)

import requests from bs4 import beautifulsoup  url = 'https://www.php.cn/link/013c0727c2f3b90ec8545f5062f75360' soup = BeautifulSoup(requests.get(url).content, 'html.parser')  plants_table = soup.select_one('#section-PLANTS') # 只选取包含  标签的行,自动跳过表头/空行 for row in plants_table.select('tr:has(a)'):     print(row.find('a').get_text(strip=True))

? tr:has(a) 是现代 BeautifulSoup(配合 lxml 或 html.parser)支持的 CSS 选择器,语义清晰、性能优秀,无需手动判断 None。

✅ 方案二:显式空值检查(兼容性最强)

for row in plants_table.find_all('tr'):     link = row.find('a')     if link:  # 确保 link 不为 None         print(link.get_text(strip=True))

✅ 方案三:使用 find_next() 或 select_one() 避免链式调用风险

for row in plants_table.find_all('tr'):     link = row.select_one('a')  # 返回 None 或 Tag,更安全     if link:         print(link.get_text(strip=True))

⚠️ 注意事项

  • 永远不要对 find() / select_one() 的返回值直接链式调用 .text 或 [‘href’],除非你 100% 确认该元素必然存在;
  • 使用 .get_text(strip=True) 替代 .contents[0] 更鲁棒——它能合并嵌套文本节点并去除首尾空白;
  • 若目标页面结构复杂(如含 / ),建议先用 soup.select(‘#section-PLANTS tbody tr’) 显式限定范围;

  • 在生产环境中,务必添加异常处理与网络请求超时:
    try:     resp = requests.get(url, timeout=10)     resp.raise_for_status()     soup = BeautifulSoup(resp.content, 'html.parser') except (requests.RequestException, AttributeError) as e:     print(f"解析失败: {e}")
  • 通过合理选用 CSS 选择器或前置空值校验,即可彻底规避 NoneType 错误,让表格数据提取既准确又健壮。

text=ZqhQzanResources