Advertisement

嵩天《Python网络爬虫与信息提取》实例2:中国大学排名定向爬虫

阅读量:

在介绍完requests库和robots协议后,嵩天老师又重点介绍了如何通过BeautifulSoup库进行网页解析和信息提取。这一部分就是在前面内容的基础上,综合运用requests库和BeautifulSoup库的知识,对软科中国大学排名进行定向爬取。

说明:爬虫练习仅为学习,不做商用,如有侵权,烦请联系删除!

目标网页:https://www.shanghairanking.cn/rankings/bcur/2021

爬取目标:爬取上海软科官网提供的中国最好大学排名,并在IDLE页面打印输出大学名称、排名、省市、总分信息

相关库名:requests/BeautifulSoup

目录

1.网页解析

2.代码设计

3.运行结果

4.问题记录

1.网页解析

打开上述软科中国大学排名页面,选择最新的2021年排名,页面显示如下:

查看页面源代码,Ctrl+F搜索北京大学,可以定位到与大学排名相关的代码位置,观察代码可知,所有的大学排名信息被封装在标签中,其中每一个大学排名的信息则被封装在标签中,大学排名、大学名称、省市、总分等信息都封装在其下的标签中,这里需要注意的是,新版的大学排名中,大学名称对应的td标签中还包括中英文校名、LOGO等信息,这些信息又分别封装在标签中,所以要仅打印中文大学名称的话,需要具体到查找属性为'name-cn'的a标签并存储其字符串。

2.代码设计

结合2021年新版的中国大学排名网页情况,对嵩天老师提供的中国大学排名爬虫源代码做了简单的修改,完整代码如下,相关讲解见注释:

复制代码
 #实例:中国大学排名定向爬虫

    
 import requests
    
 from bs4 import BeautifulSoup
    
 #从beautifulsoup4库中引入BeautifulSoup类,注意大小写
    
 import bs4
    
 #注意这里需要再引入bs4库,因为后面有bs4.element.Tag语句,不引入会报错
    
  
    
 def getHTMLText(url):
    
 #定义获取网页源代码文本内容的函数
    
     try:
    
     r=requests.get(url,timeout=30)
    
     r.raise_for_status()
    
     r.encoding=r.apparent_encoding
    
     return r.text
    
     except:
    
     print('获取网页信息失败')
    
  
    
 def fillUnivList(ulist,html):
    
 #定义获取大学排名信息的函数
    
     soup=BeautifulSoup(html,'html.parser')
    
     #使用html.parser解析器解析返回的html源代码文本
    
     for tr in soup.find('tbody').children:
    
     #使用for循环查找tbody标签,并遍历其子孙节点
    
     if isinstance(tr,bs4.element.Tag):
    
     #检测是否为tag标签不是则过滤
    
         tds=tr('td')
    
         #查找tr标签下所有的td标签,并将其内容保存为tds
    
         a=tr('a','name-cn')
    
         #由于新版的排名中,td下的大学名称信息还包括中英文校名、LOGO等,这些又分别封装在a标签中,所以这里需要具体到查找属性为'name-cn'的a标签并存储其字符串,即大学的中文名称
    
         ulist.append([tds[0].string.strip(),a[0].string.strip(),tds[2].text.strip(),tds[4].string.strip()])
    
         #依次将大学排名、大学名称、省市(这个用string会报错)、总分信息保存到列表中,使用.strip()删除结尾的字符
    
  
    
 def printUnivList(ulist,num):
    
 #定义打印大学排名信息的函数,这里的num值打印大学的数量
    
     printmode='{0:^10}\t{1:{4}^10}\t{2:{4}^10}\t{3:^10}'
    
     #引入一个输出模板的变量这里的{4}指代中文空格chr(12288),用以填充大学名称其余空格,使得输出的字符能够对齐,并且这里选择把字符长度都设置为10,否则表头和打印内容总是对不齐
    
     print(printmode.format('排名','大学名称','省市','总分',chr(12288)))
    
     #打印表头的信息并设置打印格式
    
     for i in range(num):
    
     u=ulist[i]
    
     #使用for循环依次打印ulist列表中存储的大学排名信息,用变量u代表每所大学的信息
    
     print(printmode.format(u[0],u[1],u[2],u[3],chr(12288)))
    
     #设置打印格式依次打印每所大学的排名、大学名称、省市、总分信息
    
  
    
 def main():
    
     uinfo=[]
    
     #定义一个空列表用于填充装取大学排名信息
    
     url='https://www.shanghairanking.cn/rankings/bcur/2021'
    
     #给出大学排名网页
    
     html=getHTMLText(url)
    
     #调用函数获取网页源代码文本
    
     fillUnivList(uinfo,html)
    
     #调用函数获取大学排名信息并填充到列表中
    
     printUnivList(uinfo,30)
    
     #调用打印大学排名信息的函数,并打印排名前30的大学信息
    
  
    
 main()
    
    
    
    

3.运行结果

运行代码后,IDLE页面结果显示如下:

4.问题记录

这里再记录一些代码测试过程中的报错信息,首先是一个命名错误:

NameError: name 'bs4' is not defined

其实是因为后面if isinstance(tr,bs4.element.Tag) 这里用到了bs4而我们只引入了bs4库中的BeautifulSoup类,再在开头加上import bs4单独引入bs4库就好了。

此外,省市的打印如果用.string的话会报错如下:

TypeError: unsupported format string passed to NoneType.format

即此时省市信息为None值无法有效打印,修改为.text就能正常打印省市信息了。

再者,如果按照嵩天老师的代码直接打印.string的字符信息的话,发现打印出的大学排名信息是没有对齐且跨行了的,如下图所示:

解决这一问题的方案是在.string后再加入.strip()删除结尾可能存在的多余的字符。

这些问题也都在上面的完整代码中对应位置作了相应说明。之前看慕课时也练习过这个案例,当时也遇到了挺多问题的,而且也不能完全理解全部代码的含义,在有了些许经验之后再回来练习,很快就调整好代码成功打印出了目标信息,也对相关代码有了更好的理解,果然还是Practice makes perfects.

参考资料:
嵩天. Python网络爬虫与信息提取[EB/OL].
https://www.icourse163.org/course/BIT-1001870001.

全部评论 (0)

还没有任何评论哟~