Python网页爬虫:如何独立提取学生姓名、学号等字段
问题描述
尝试爬取某网站学生姓名、学号、分数及录取状态数据,使用代码:
student_data = soup.findAll('div', attrs= {'class':'fontLight'})
执行以下代码时报错:
for store in student_data: name = store.h5.name.text
报错信息:
'NoneType' object has no attribute 'name'
改为以下代码仅能获取最后一条状态数据:
for store in student_data: name = store.h5.text
结果:
'Eligible for Admission'
执行append操作得到无法拆分的合并列表:
for store in student_data: name = store.h5.text candidate_name.append(name)
结果:
['muhammad bilal', '346010', '193', 'Eligible for Admission']
目标网页HTML结构(简化后):
<div class="row"> <div class="col-sm-2"></div> <div class="col-sm-5"> <h3 class="fontMedium" style="color:#29a2d8">Student Details</h3> <div style="display: flex;"> <div class="fontBold" style="flex: 1;"><h5>Name</h5></div> <div class="fontLight" style="flex: 1;"><h5 id="name">muhammad bilal</h5></div> </div> <div style="display: flex;"> <div class="fontBold" style="flex: 1;"><h5>Student Rollno</h5></div> <div class="fontLight" style="flex: 1;"><h5 id="rollno">346010</h5></div> </div> </div> <div class="col-sm-3"> <h3 class="fontMedium" style="color:#29a2d8">Result</h3> <div style="display: flex;"> <div class="fontBold" style="flex: 1.3;"><h5>Obtained Marks</h5></div> <div class="fontLight" style="flex: 1;"><h5 class="fontMedium" id="omarks">193</h5></div> </div> <div style="display: flex;"> <div class="fontBold" style="flex: 1.3;"><h5>Result Status</h5></div> <div class="fontLight" style="flex: 1;"><h5 id="" style="color:green"><b>Eligible for Admission</b></h5></div> </div> </div> </div>
解决方案
方法1:按索引直接提取
从结果可见,student_data是包含4个元素的列表,顺序正好对应姓名、学号、分数、录取状态,直接通过索引取值即可:
student_data = soup.findAll('div', attrs={'class':'fontLight'}) # 单独提取每个字段 name = student_data[0].h5.text.strip() roll_no = student_data[1].h5.text.strip() obtained_marks = student_data[2].h5.text.strip() admission_status = student_data[3].h5.text.strip() # 整理成字典更易使用 student_info = { "姓名": name, "学号": roll_no, "分数": obtained_marks, "录取状态": admission_status }
方法2:通过元素ID定位(更精准)
前三个字段的h5标签有唯一ID(name、rollno、omarks),直接通过ID定位更可靠;录取状态可通过父容器文本定位:
# 直接通过ID提取 name = soup.find('h5', id='name').text.strip() roll_no = soup.find('h5', id='rollno').text.strip() obtained_marks = soup.find('h5', id='omarks').text.strip() # 提取录取状态:找到包含"Result Status"的fontBold元素,取其兄弟fontLight元素的文本 status_label = soup.find('div', class_='fontBold', string=lambda text: 'Result Status' in text.strip()) admission_status = status_label.find_next_sibling('div', class_='fontLight').h5.text.strip() student_info = { "姓名": name, "学号": roll_no, "分数": obtained_marks, "录取状态": admission_status }
方法3:自动配对标签与值(扩展性更强)
若页面有更多字段,遍历所有flex容器,自动将左侧fontBold标签和右侧fontLight值配对:
student_info = {} # 找到所有包含字段的flex容器 flex_containers = soup.find_all('div', style='display: flex;') for container in flex_containers: # 获取标签文本并清理空格 label = container.find('div', class_='fontBold').h5.text.strip() # 获取值文本并清理空格 value = container.find('div', class_='fontLight').h5.text.strip() # 存入字典 student_info[label] = value # 最终student_info为: # {'Name': 'muhammad bilal', 'Student Rollno': '346010', 'Obtained Marks': '193', 'Result Status': 'Eligible for Admission'}
报错原因说明
store.h5.name.text报错是因为store.h5.name获取的是标签名(字符串h5),而非属性,正确写法是store.h5.text获取标签内文本。- 单独循环只保留最后一条数据是因为每次循环覆盖了
name变量;append操作是正常的列表追加行为,你需要的是将列表元素对应到不同字段而非合并存储。
内容的提问来源于stack exchange,提问作者Agha Sahaab
相关产品推荐
相关产品推荐

