如何处理BeautifulSoup爬取数据生成DataFrame时的缺失值问题
解决方法
一、爬取阶段处理(推荐,彻底避免信息错位)
核心逻辑是按单个学生的信息区块来爬取,每个学生的名字、导师、邮箱都从专属容器内提取,天然保证信息一一对应,缺失的邮箱直接留空或存None。你需要根据网页实际结构调整学生容器的选择器(比如假设每个学生信息都在div.person标签内):
import pandas as pd import re from bs4 import BeautifulSoup with open('Biology.html') as file: soup = BeautifulSoup(file, 'html.parser') scrapped_data = [] # 找到所有学生的独立容器(请替换成网页实际的容器选择器) person_blocks = soup.find_all('div', class_='person') for block in person_blocks: # 提取当前学生的名字 name_elem = block.find('strong') student_name = name_elem.text.strip() if name_elem else None # 提取导师信息 supervisor_elem = block.find('div', class_='person-job-titles') supervisor = supervisor_elem.contents[0].split(":")[-1].strip() if supervisor_elem else None # 提取邮箱,没有则留空 email_elem = block.find('a', href=re.compile('^mailto')) email = email_elem.attrs['title'] if email_elem else None # 将当前学生的信息存入列表 scrapped_data.append({ 'Names': student_name, 'Supervisors': supervisor, 'Emails': email }) # 生成DataFrame,缺失邮箱会自动显示为NaN df = pd.DataFrame(scrapped_data)
这种方法从根源上解决了错位问题,因为每个学生的信息都是绑定在一起采集的,不管有没有邮箱,每条数据都对应一个学生。
二、生成DataFrame时补全(仅当无法找到学生容器时使用)
如果实在无法定位到单个学生的容器,只能分别爬取三个列表,可以通过补全缺失值来对齐长度,但前提是三个列表的顺序必须完全对应(比如第i个名字对应第i个导师、第i个邮箱):
import pandas as pd import re from bs4 import BeautifulSoup with open('Biology.html') as file: soup = BeautifulSoup(file, 'html.parser') # 提取名字列表 name_tags = soup.find_all('strong') full_name = [tag.text.strip() for tag in name_tags[:-1]] # 提取导师列表 supervisor_tags = soup.find_all('div', class_='person-job-titles') supervisor_list = [tag.contents[0].split(":")[-1].strip() for tag in supervisor_tags] # 提取邮箱列表 email_tags = soup.find_all('a', href=re.compile('^mailto')) email_add = [tag.attrs['title'] for tag in email_tags] # 对齐三个列表的长度,缺失位置用None填充 max_len = max(len(full_name), len(supervisor_list), len(email_add)) full_name += [None] * (max_len - len(full_name)) supervisor_list += [None] * (max_len - len(supervisor_list)) email_add += [None] * (max_len - len(email_add)) # 生成DataFrame df = pd.DataFrame({ 'Names': full_name, 'Supervisors': supervisor_list, 'Emails': email_add })
问题根源说明
你之前的代码直接将长度可能不一致的三个列表打包成字典,pandas会自动截断到最短列表的长度,导致行数减少;同时如果邮箱的顺序和名字不匹配,就会出现信息错位。上述两种方法分别从采集逻辑和数据补全两个层面解决了这个问题。
内容的提问来源于stack exchange,提问作者possizola
相关产品推荐
相关产品推荐

