[python爬虫] 爬取学院老师信息
Posted Jucway
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[python爬虫] 爬取学院老师信息相关的知识,希望对你有一定的参考价值。
任务
- java 课堂的加分作业,原本应该使用java进行爬虫,但是在爬虫方面这个是python的优势,所以就趁此机会学习一下python爬虫,没有使用 java 进行实验;
- 过程比较辛苦,没有系统学过爬虫,但是python还是经常用的;初次尝试,很多不足,在此记录,下次完善!
思路
- 定位到提取信息的位置
- 将对应的信息提取出来,存到字典里
- 由于不是每个老师的信息都是相同的,需要进行判断处理
- 判断的过程中,对于关键字也是存在差异的,例如有的老师显示邮箱地址,有的是邮件地址;有的是讲课课程,有的是授课课程,有的是部门有的是研究所;还有的是,网页上信息多行写到一个段内,有的是一个信息一段,这个过程增加了信息提取的难度;这也让自己明白了,写代码一定要规范,相同的属性要用同一套标准,不能多种格式;
分析
分析网页
-
进入网址:
http://jsj.gzhu.edu.cn/szdw1/jsjkxywlgcxysz.htm
-
鼠标右键选择检查元素(火狐或者谷歌)快捷键 F12
结合代码
r = requests.get(url,headers=headers)
#设置编码方式,否则出现乱码
r.encoding='utf-8'
html = bs4.BeautifulSoup(r.text, "html.parser")
#找到网页标签为 "ul" 下 class_="sdfasdjsf clearfloat" 下的所有 "li" 列表标签 每个列表代表一个老师
all_job = html.find("ul", class_="sdfasdjsf clearfloat").find_all("li") # 找到所有列表 返回是列表代表教授,副教授,讲师
变量这三个块 找到信息类的标志
for data in all_job:
zhichenk = data.find("div", class_="fasf").get_text() # 找到div class_="fast" 教授这个块
name = data.find("div", class_="mclb") # 找到对应的"mclb"类
进入到教授列表下,变量找到每个老师的下面和消息链接
for j in range(len(name)): # 循环每个老师 第一次进入的是教授这个列表的老师,第二次进入副教授,第三次进入讲师
l = len(name)
k = j*2+1 # 这个是网页是每个老师信息出现之后会空一行,所以有用的信息在奇数行下
if k>=len(name): # 越界退出
break
a = name.contents[k] # 获取这一行的信息
m_href = a.attrs['href'] # 找到进入老师详细信息的链接
xinming = a.attrs['title'] # 这里通过debug 发现title 属性是教师名称
result["姓名"][count] = xinming # 在字典对应位置写入
m_href = "http://jsj.gzhu.edu.cn/"+m_href[3:] # 提出出来的连接是相对地址,去掉开头.. 添加上完整地址
r1 = requests.get(m_href, headers=headers) # 请求新的链接进入信息页面
r1.encoding='utf-8'
bs1 = bs4.BeautifulSoup(r1.text, 'html.parser')
sour = bs1.find('div', id='vsb_content').find_all('p') # 信息在id 为"vsb_content" 的段内
for x in sour: # 遍历每个段
inflag = count
str = x.text
str = str.lstrip() # 取出信息的左空格
# str = "".join(str.split()) #
if str.count(":") >= 2: # 这一步判断是因为网页的信息有部分没有规矩,不能直接提取
s = str.split(" ") # 这里是去除空格
for i in s:
title = i.split(":") # 针对多行信息写到一个段落内的
if len(title) == 1:
continue
# str = "".join(i.split())
if title[0] == "个人主页":
result["个人主页"][inflag] = title[1]
elif title[0] == "办公地点":
result["办公地点"][inflag] = title[1]
elif title[0] == "办公电话":
result["办公电话"][inflag] = title[1]
elif title[0] == "职务":
result["职称"][inflag] = title[1]
elif title[0] == "电子邮箱" or title[0] == "个人邮箱":
result["电子邮件"][inflag] = title[1]
elif title[0] == "讲述课程":
result["讲授课程"][inflag] = title[1]
elif title[0] == "部门":
result["系、研究所"][inflag] = title[1]
else:
result[title[0]][inflag] = title[1]
continue
str = "".join(str.split()) # 去除 \\xa0\\xa0\\xa0\\xa也就是去除空格,
if str == '\\n' or str == '' or len(str)==1 or str == '\\r\\n' or str == '\\xa0\\xa0\\xa0':
continue
str = str.strip()
title = str.split(":")
if title[0] == "个人主页":
result["个人主页"][inflag] = title[1]
elif title[0] == "办公地点":
result["办公地点"][inflag] = title[1]
elif title[0] == "办公电话":
result["办公电话"][inflag] = title[1]
elif title[0] == "职务":
result["职称"][inflag] = title[1]
elif title[0] == "电子邮箱" or title[0] == "个人邮箱":
result["电子邮件"][inflag] = title[1]
elif title[0] == "讲述课程":
result["讲授课程"][inflag] = title[1]
elif title[0] == "部门":
result["系、研究所"][inflag] = title[1]
else:
result[title[0]][inflag]= title[1]
infalg = j
count = count + 1
爬取结果
- 由于是公共网站的资源,但是关键信息还是得遮挡一下;
代码
文件
# _*_coding:utf-8_*_
# create by Jucw on 2021/11/25 11:44
import requests
import bs4
import re
import pandas as pd # 存表格
n = 66 # 估计大概多少个教师
# 存储数据,这是对于每个老师的个人信息不是统一的,将没有的信息用空字符串填充
result = "姓名": [""]*n,
"职称": [""]*n,
"系、研究所":[""]*n,
"研究领域":[""]*n,
"办公电话":[""]*n,
"电子邮件":[""]*n,
"讲授课程":[""]*n,
"个人主页":[""]*n,
"办公地点":[""]*n
# 计算机学院的网址
url = "http://jsj.gzhu.edu.cn/szdw1/jsjkxywlgcxysz.htm"
# 网址设置了反爬虫,添加请求头模拟浏览器登录
headers =
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0'
# 请求数据
r = requests.get(url,headers=headers)
# 设置编码方式,否则出现乱码
r.encoding='utf-8'
html = bs4.BeautifulSoup(r.text, "html.parser")
# 找到网页标签为 "ul" 下 class_="sdfasdjsf clearfloat" 下的所有 "li" 列表标签 每个列表代表一个老师
all_job = html.find("ul", class_="sdfasdjsf clearfloat").find_all("li")
# count 代表第几个老师,用于将数据写入到字典对应的位置
count = 0
#
for data in all_job:
zhichenk = data.find("div", class_="fasf").get_text() # 找到div class_="fast" 教授这个块
name = data.find("div", class_="mclb") # 找到对应的"mclb"类
for j in range(len(name)): # 循环每个老师 第一次进入的是教授这个列表的老师,第二次进入副教授,第三次进入讲师
l = len(name)
k = j*2+1 # 这个是网页是每个老师信息出现之后会空一行,所以有用的信息在奇数行下
if k>=len(name): # 越界退出
break
a = name.contents[k] # 获取这一行的信息
m_href = a.attrs['href'] # 找到进入老师详细信息的链接
xinming = a.attrs['title'] # 这里通过debug 发现title 属性是教师名称
result["姓名"][count] = xinming # 在字典对应位置写入
m_href = "http://jsj.gzhu.edu.cn/"+m_href[3:] # 提出出来的连接是相对地址,去掉开头.. 添加上完整地址
r1 = requests.get(m_href, headers=headers) # 请求新的链接进入信息页面
r1.encoding='utf-8'
bs1 = bs4.BeautifulSoup(r1.text, 'html.parser')
sour = bs1.find('div', id='vsb_content').find_all('p') # 信息在id 为"vsb_content" 的段内
for x in sour: # 遍历每个段
inflag = count
str = x.text
str = str.lstrip() # 取出信息的左空格
# str = "".join(str.split()) #
if str.count(":") >= 2: # 这一步判断是因为网页的信息有部分没有规矩,不能直接提取
s = str.split(" ")
for i in s:
title = i.split(":")
if len(title) == 1:
continue
# str = "".join(i.split())
if title[0] == "个人主页":
result["个人主页"][inflag] = title[1]
elif title[0] == "办公地点":
result["办公地点"][inflag] = title[1]
elif title[0] == "办公电话":
result["办公电话"][inflag] = title[1]
elif title[0] == "职务":
result["职称"][inflag] = title[1]
elif title[0] == "电子邮箱" or title[0] == "个人邮箱":
result["电子邮件"][inflag] = title[1]
elif title[0] == "讲述课程":
result["讲授课程"][inflag] = title[1]
elif title[0] == "部门":
result["系、研究所"][inflag] = title[1]
else:
result[title[0]][inflag] = title[1]
continue
str = "".join(str.split()) #
if str == '\\n' or str == '' or len(str)==1 or str == '\\r\\n' or str == '\\xa0\\xa0\\xa0':
continue
str = str.strip()
title = str.split(":")
if title[0] == "个人主页":
result["个人主页"][inflag] = title[1]
elif title[0] == "办公地点":
result["办公地点"][inflag] = title[1]
elif title[0] == "办公电话":
result["办公电话"][inflag] = title[1]
elif title[0] == "职务":
result["职称"][inflag] = title[1]
elif title[0] == "电子邮箱" or title[0] == "个人邮箱":
result["电子邮件"][inflag] = title[1]
elif title[0] == "讲述课程":
result["讲授课程"][inflag] = title[1]
elif title[0] == "部门":
result["系、研究所"][inflag] = title[1]
else:
result[title[0]][inflag]= title[1]
infalg = j
count = count + 1
df = pd.DataFrame(result) #
df.to_csv("jiaoshi.csv", encoding="utf_8_sig") # 保存信息
展望
- python 爬虫设计正则表达式,xpath,由于不太熟悉,没能很好优化!
- 下一次学习!
以上是关于[python爬虫] 爬取学院老师信息的主要内容,如果未能解决你的问题,请参考以下文章