使用BeautifulSoup爬取数据存入Pandas DataFrame时部分单元格值缺失
解决网页爬取中部分数据缺失的问题
问题分析
你的代码出现数据缺失,核心是两处逻辑没处理页面结构的异常情况:
- 电话号码缺失:第一行的电话单元格无有效文本,直接调用
replace会导致None值存入列表,最终在DataFrame中显示为空。 - 邮政编码缺失:依赖
next_element获取邮编的逻辑不稳定,部分行的地址单元格DOM结构不同,next_element不存在或无有效文本,导致提取失败。
修复方案
1. 健壮处理电话号码提取
先判断电话文本是否存在,再做格式处理,不存在时存入空值:
# 替换原Phone.append行 phone_text = cells[5].find(text=True) Phone.append(phone_text.replace('T: ', '') if phone_text else '')
2. 用正则提取邮政编码(更可靠)
加拿大邮编固定为A1A 1A1格式(字母+数字+字母+空格+数字+字母+数字),直接从地址单元格的所有文本中匹配该格式,摆脱对DOM结构的依赖:
import re # 替换原PostalCode.append行 address_cell_text = cells[4].get_text(strip=True, separator=' ') postal_match = re.search(r'[A-Z]\d[A-Z] \d[A-Z]\d', address_cell_text) PostalCode.append(postal_match.group() if postal_match else '')
完整修改后的代码
from urllib.request import urlopen from bs4 import BeautifulSoup import pandas as pd import re schools = "https://www.winnipegsd.ca/page/9258/school-directory-a-z" page = urlopen(schools) soup = BeautifulSoup(page, features="html.parser") table_ = soup.find('table') Name = [] Address = [] PostalCode = [] Phone = [] Grades = [] Website = [] for row in table_.findAll("tr"): cells = row.findAll('td') if len(cells) == 6: # 提取学校名称 name_text = cells[1].find(text=True) Name.append(name_text if name_text else '') # 提取地址 address_text = cells[4].find(text=True) Address.append(address_text if address_text else '') # 正则提取邮编 address_cell_text = cells[4].get_text(strip=True, separator=' ') postal_match = re.search(r'[A-Z]\d[A-Z] \d[A-Z]\d', address_cell_text) PostalCode.append(postal_match.group() if postal_match else '') # 提取并处理电话 phone_text = cells[5].find(text=True) Phone.append(phone_text.replace('T: ', '') if phone_text else '') # 提取年级 grades_text = cells[2].find(text=True) Grades.append(grades_text if grades_text else '') # 提取网站链接 link_tag = cells[1].find('a') Website.append('https://www.winnipegsd.ca' + link_tag['href'] if link_tag else '') # 构建DataFrame df = pd.DataFrame({ 'Name': Name, 'Street Address': Address, 'Postal Code': PostalCode, 'Phone Number': Phone, 'Grades': Grades, 'Website': Website }) df.to_csv("file.tsv", sep="\t", index=False)
额外优化建议
- 用字典直接构建DataFrame更清晰,避免逐个列赋值可能出现的长度不匹配问题。
- 对所有字段都做空值判断,避免因页面结构变化导致的报错或数据缺失。
内容的提问来源于stack exchange,提问作者thewire
相关产品推荐
相关产品推荐

