在上学期学习了爬虫的一些知识,主要学习了运用正则表达式和标签法对网站内容进行爬取,经过学习后发现,标签法易于理解,但是可能写的代码较长,不够简洁;而正则表达式方法不太易于理解,在编写正则表达式时可能需要谨慎地思考如何写,但是写出来地代码会比较简洁。我这里采用标签法来爬虫,其中一个主要地原因是我用标签法写代码的时间会比运用正则表达式写的时间要短,效率要高一点。
这里我就不详细地介绍爬虫的知识和正则表达式、标签的一些定义了,如果感兴趣的话本平台和其他一些平台都有非常详细的介绍,可以去搜索看看,以下的讲解适合有初步接触过这两种方法的观众。
这里要求爬取一所大学的每个学院的名称、网址及学院内部对应的专业设置,并最后汇总出excel表格,以下是所有的代码部分(为了大家的独立思考我就不把我爬取的学校的url打出来了,本文章仅仅提供思路):
from openpyxl import Workbook
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
url='' #这里填写你要爬取的学校的网址
content=requests.get(url)
content.encoding='utf8'
soup=BeautifulSoup(content.text,'lxml')
pattern=soup.findAll('li')[4].findAll('a')[0] #找首页里的机构设置对应的li标签
jigoulink=pattern.get('href') #找href的值,即找出机构设置的网址
jigoulink=urljoin(url,jigoulink) #jigoulink为机构设置网址
content=requests.get(jigoulink)
content.encoding='utf8'
soup=BeautifulSoup(content.text,'lxml')
pattern=soup.findAll('div',{'class':'sub-nav-h'})[1] #找机构设置下的教学科研机构
pattern1=pattern.findAll('a')[3]
jiaoxuelink=pattern1.get('href') #读出教学科研机构的href值
jiaoxuelink=urljoin(url,jiaoxuelink) #jiaoxuelink为教学科研机构的网址
content=requests.get(jiaoxuelink)
content.encoding='utf8'
soup=BeautifulSoup(content.text,'lxml')
wb=Workbook()
ws=wb.active
ws['A1'] = '学院名称'
ws['B1'] = '网址'
ws['C1'] = '专业设置' #设置excel表格
pattern=soup.findAll('dl',{'class':'item'})[3] #找教学科研机构下的学院所处的大标签dl
pattern1=pattern.findAll('li') #找出每个学院的li子标签
college_name=[] #设定空列表为学院名字
url_name1=[] #设定空列表为网址名字
for table in pattern1: #对每个学院的li子标签进行循环
element1=table.find('a') #element1为每个学院的a标签
url1=element1.get('href') #url1为每个学院的官网
college1=element1.text #college1为每个学院的名称
college_name.append(college1) #把college_name加入进学院名字空列表里
url_name1.append(url1) #把url_name1加入进学院网址空列表里
for i in range(len(college_name)): #循环操作,把学院名字和网址写入excel表格
ws.cell(row=i + 2, column=1, value=college_name[i])
ws.cell(row=i + 2, column=2, value=url_name1[i])
url_name=url_name1 #把最后生成的全部网址储存在url_name变量里
#为了尽可能寻找每个学院的专业名称,且很多学院的专业存储在专业建设或人才培养或学科建设等名称不一样的地方,且所属标签很多不相同,故采用逐个寻找法
content = requests.get(url_name[0]) # 会计学院专业查找
content.encoding = 'utf8'
soup = BeautifulSoup(content.text, 'lxml')
pattern = soup.findAll('div')[59:64] #寻找专业名称所属的div标签
link_list = [] #建立储存专业名称的空列表
for html1 in pattern: #在pattern里进行循环,html1为每个专业名称对应的div标签
pattern_list = html1.text #提取专业名字
link_list.append(pattern_list) #将名字放入link_list空列表里
link_list1 = [item1.replace('\n', '').replace('\xa0', '').replace('\r', '').replace(' ', '') for item1 in
link_list] #把列表里出现的非名称的字符去掉
kuaiji_link = ','.join(link_list1) #把会计学院的每个专业名称字符串合起来变成一个总的字符串
caizheng_link='' #财政学院未找到专业建设,故为空
content = requests.get(url_name[2]) # 经济学院专业查找
content.encoding = 'utf8'
soup = BeautifulSoup(content.text, 'lxml')
pattern = soup.findAll('li')[18:23] #找出专业名称所属的li标签
link_list = []
for html1 in pattern:
pattern_list = html1.text #提取专业名字
link_list.append(pattern_list)
jingji_link = ','.join(link_list) #把经济学院的每个专业名称字符串合起来变成一个总的字符串
content = requests.get(url_name[3]) # 工商管理学院专业查找
content.encoding = 'utf8'
soup = BeautifulSoup(content.text, 'lxml')
pattern=soup.findAll('li')[28].findAll('a')[0] #此学院的专业在学科专业栏里,在首页提取学科专业的li标签,找其a标签
link = pattern.get('href') #提取href值
link1 = f'http://www.hufe.edu.cn/gsglxy/{link}' #link1为此学院的学科建设网址
content = requests.get(link1)
content.encoding = 'utf8'
soup = BeautifulSoup(content.text, 'lxml')
pattern = [soup.findAll('td')[3],soup.findAll('td')[5],soup.findAll('td')[7],soup.findAll('td')[9],
soup.findAll('td')[11]] #找出学科建设里专业名称对应的td标签
link_list = []
for html1 in pattern:
pattern_list = html1.text #提取专业名字
link_list.append(pattern_list)
link_list1 = [item1.replace('\n', '').replace('\xa0', '').replace('\r', '').
replace('简介', '') for item1 in link_list] #把linklist里的非专业名称去掉
gongguan_link = ','.join(link_list1) #把工商管理学院的每个专业名称字符串合起来变成一个总的字符串
content = requests.get(url_name[4]) # 信息技术学院专业查找
content.encoding = 'utf8'
soup = BeautifulSoup(content.text, 'lxml')
pattern = soup.findAll('div')[57:64] #找出专业名称所属的div标签
link_list = []
for html1 in pattern:
pattern_list = html1.text #提取专业名字
link_list.append(pattern_list)
link_list1 = [item1.replace('\n', '').replace('\xa0', '').replace('\r', '').replace(' ', '').
replace('简介', '') for item1 in link_list] #把linklist里的非专业名称去掉
xinxijishu_link = ','.join(link_list1) #把信息技术学院的每个专业名称字符串合起来变成一个总的字符串
faxue_link='' #法学专业未找到专业建设
content = requests.get(url_name[6]) # 外语学院专业查找
content.encoding = 'utf8'
soup = BeautifulSoup(content.text, 'lxml')
pattern = soup.findAll('li')[10].findAll('a')[0] #该学院专业在学科专业建设栏,在首页提取学科专业建设的li标签,找其a标签
link = pattern.get('href')
link1 = f'http://www.hufe.edu.cn/wgyxy/{link}' #link1为此学院的学科专业建设网址
content = requests.get(link1)
content.encoding = 'utf8'
soup = BeautifulSoup(content.text, 'lxml')
pattern = soup.findAll('div')[23:27] #找出学科专业建设里专业名称对应的div标签
link_list = []
for html1 in pattern:
pattern_list = html1.text #提取专业名字
link_list.append(pattern_list)
link_list1 = [item1.replace('\n', '').replace('\xa0', '') for item1 in link_list] #把linklist里的非专业名称去掉
waiyu_link = ','.join(link_list1) #把外语学院的每个专业名称字符串合起来变成一个总的字符串
content = requests.get(url_name[7]) # 工程管理学院专业查找
content.encoding = 'utf8'
soup = BeautifulSoup(content.text, 'lxml')
pattern = soup.findAll('div')[106:110] #找出专业名称所属的div标签
link_list = []
for html1 in pattern:
pattern_list = html1.text #提取专业名字
link_list.append(pattern_list)
link_list1 = [item1.replace('简介', '') for item1 in link_list] #把linklist里的非专业名称去掉
gongcheng_link = ','.join(link_list1) #把工程管理学院的每个专业名称字符串合起来变成一个总的字符串
content = requests.get(url_name[8]) #人文艺术学院专业查找
content.encoding = 'utf8'
soup = BeautifulSoup(content.text, 'lxml')
pattern = soup.findAll('li')[17:20] #找出专业名称所属的li标签
link_list = []
for html1 in pattern:
pattern_list = html1.text #提取专业名字
link_list.append(pattern_list)
renwen_link = ','.join(link_list) #把人文艺术学院的每个专业名称字符串合起来变成一个总的字符串
content = requests.get(url_name[9]) # 统计与数学学院专业查找
content.encoding = 'utf8'
soup = BeautifulSoup(content.text, 'lxml')
pattern = soup.findAll('li')[18:20] #找出专业名称所属的li标签
link_list = []
for html1 in pattern:
pattern_list = html1.text #提取专业名字
link_list.append(pattern_list)
tongshu_link = ','.join(link_list) #把统计与数学学院的每个专业名称字符串合起来变成一个总的字符串
content = requests.get(url_name[10]) # 体育学院专业查找
content.encoding = 'utf8'
soup = BeautifulSoup(content.text, 'lxml')
pattern = soup.findAll('div')[77:80] #找出专业名称所属的div标签
link_list = []
for html1 in pattern:
pattern_list = html1.text #提取专业名字
link_list.append(pattern_list)
link_list1 = [item1.replace('\n', '').replace('\xa0', '').replace('\r', '').
replace('简介', '') for item1 in link_list] #把linklist里的非专业名称去掉
tiyu_link = ','.join(link_list1) #把体育学院的每个专业名称字符串合起来变成一个总的字符串
makesi_link='' #马克思主义学院未找到专业建设
guoji_link = '' # 国际学院未找到专业建设
xueyuan_link = '' # 学院未找到专业建设
content = requests.get(url_name[14]) # 地理学院专业查找
content.encoding = 'utf8'
soup = BeautifulSoup(content.text, 'lxml')
pattern = soup.findAll('li')[52:54] #找出专业名称所属的li标签
link_list = []
for html1 in pattern:
pattern_list = html1.text #提取专业名字
link_list.append(pattern_list)
link_list1 = [item1.replace('\n', '').replace('介绍','') for item1 in link_list]
dili_link = ','.join(link_list1) #把地理学院的每个专业名称字符串合起来变成一个总的字符串
jixu_link = '' # 继续教育学院未找到专业建设
link_result=[kuaiji_link,caizheng_link,jingji_link,gongguan_link,xinxijishu_link,faxue_link,waiyu_link,
gongcheng_link,renwen_link,tongshu_link,tiyu_link,makesi_link,guoji_link,xueyuan_link,
dili_link,jixu_link] #把每个学院的专业字符串加入到link_result列表里
for i in range(len(college_name)):
ws.cell(row=i + 2, column=3, value=link_result[i]) #把link_result里的专业名称写入excel里
wb.save('xxx的专业设置.xlsx')
代码里面有提供详细的注释,下面我简明地讲解一些地方:
1.爬取思路:首先我找到该学院的网址,然后在首页的教学科研机构找到各学院的名字,然后点开各学院的官网之后主要是去首页的学科建设/专业建设里找有没有写专业设置,如果有的话就爬取,没有的话就列为空集。
2.流程简化:我写完代码后发现有些地方是可以简化的,比如:
content=requests.get(url)
content.encoding='utf8'
soup=BeautifulSoup(content.text,'lxml')
这个是经典的三件套,可以直接定义一个函数(用def),这样后面再写的话就只用一行就可以搞定了, 而不用再写三行;然后其实后面研究了一下,如果想要简化代码行数的话最好结合正则表达式,找出一些地方相同的表达式就可以大大简化代码了,需要认真的思考,标签法就比较适合想要快速地进行爬取,但是代码量是真的多,如果有人有更好地方法欢迎在评论区里补充!
3.一些地方的解释:
①有初步接触过爬虫的小伙伴应该也有了解过,无论是正则表达式还是标签法,都要去网站的源代码里进行相应的寻找,发现有很多人打开开发者工具时习惯用右键-检查来打开,这里提供一个小方法,直接点击键盘上的F12键就可以打开啦。
②如果想在源代码页面搜索某个标签,比如div,那么可以在源代码页面在键盘上点击ctrl+F,会出现这个框框:
在里面搜索<div>就好了
③关于在官网里读出教学科研机构网页和学院网页:这里稍微提一下,注释里的也比较清楚了。我们进行爬取的时候,去教学科研机构那里点击进去查看里面的内容,会发现网址不同了,所以我们需要获取对应的网址,才能进一步获取内容,以爬取教学科研机构的网址为例,打开学院官网,鼠标移动时发现教学科研机构在机构设置里面,于是先找大标签div,然后寻找教学科研机构第二个'class':'sub-nav-h',所以就是:soup.findAll('div',{'class':'sub-nav-h'})[1],一般来说,教学科研机构对应的网址的后缀在a标签的href那里,所以我们寻找位于第几个a标签,get a标签里的href对应的值,然后用urljoin把网址连接在一起,就可以出来教学科研机构对应的网址了,学院的网址的爬取方法也类似,我这里是用了一个循环来获取的,有个非常重要的点,每次访问网址时,要先用三件套(2.里面说的),这样才能用soup去爬取该网址里对应的内容。
需要注意的点大致就是这么多了,如果有什么不明白的欢迎在评论区里留言,一起探讨,一起进步!