天天看点

用python爬取2017年中国最好大学排名

爬取2017年中国最好大学排名

在学习中国大学慕课网的python网络爬虫与信息提取时,有这么一道题,要求我们爬取2016年的中国最好大学排名链接在这,按照题目要求很快便可以爬取到我需要的排名顺序。代码如下

import requests
from bs4 import BeautifulSoup
import bs4

def getedhtml(url, code='utf-8'):
    kv = {'user-agent': 'Mozilla/5.0'}#如果网站有反爬虫措施,需要改变headers,来伪装自己
    try:
        r = requests.get(url, headers=kv, timeout=30)
        r.raise_for_status()
        r.encoding = code
        return r.text
    except:
        return ''

def returned(html, list, num):
    count = 0                                           #对加入列表中的信息进行计数
    soup = BeautifulSoup(html, 'html.parser')
    info = soup.find('tbody', 'hidden_zhpm').children
    for tr in info:
        if count >= num:
            break                                       #如果以及满足所需要的高校数,就可以退出了
        if isinstance(tr, bs4.element.Tag):
            count += 1
            tds = tr.find_all('td')
            list.append([tds[0].string, tds[1].string, tds[3].string])

def printed(list, num):
    print('{0:^10}\t{1:{3}^10}\t{2:^10}'.format('排名', '高校', '分数', chr(12288)))
    for i in range(num):
        L = list[i]
        print('{0:^10}\t{1:{3}^10}\t{2:^10}'.format(L[0], L[1], L[2], chr(12288)))


def main():
    list = []
    url = 'http://www.zuihaodaxue.com/zuihaodaxuepaiming2016.html'
    num = int(input('请问要查询2016前多少名的高校呢:'))
    html = getedhtml(url)
    returned(html, list, num)
    printed(list, num)

main()
           

但是当我准备继续爬取2017年的排名时,却发现程序并没有如期爬取我要的名次。并给我报出如下错误

TypeError: unsupported format string passed to NoneType.__format__
           

于是我便打开2017年中国最好大学网站,查看其源代码链接

当我锁定到源代码中的排名部分时,发现了问题所在。

用python爬取2017年中国最好大学排名

在图中的排名子节点“1”所对应的地方并非是一个<tr>完整的子节点,“1”并没有被一对完整的标签所包围,所以tds[0]实际上是被第一个<td>标签所包围的所有内容,而这相当于把后续所有内容全给装进去了,所以肯定没有办法对其进行string操作,来获得其排名。

由于字符1仍是第一的<td>标签下的第一个子节点,所以我打算通过bs4库的contents方法来获得这个排名,由于是第一个子节点,那么tds[0].contents[0]就是我们所需要的排名。重新修改的代码如下

# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup
import bs4

def getedhtml(url, code='utf-8'):
    kv = {'user-agent': 'Mozilla/5.0'}#网站有反爬虫措施,需要改变headers,来伪装自己
    try:
        r = requests.get(url, headers=kv, timeout=30)
        r. raise_for_status()
        r.encoding = code
        return r.text
    except:
        return ''

def returned(html, list, num):
    count = 0                                           #对加入列表中的信息进行计数
    soup = BeautifulSoup(html, 'html.parser')
    info = soup.find('tbody', 'hidden_zhpm').children
    for tr in info:
        if count >= num:
            break                                       #如果以及满足所需要的高校数,就可以退出了
        if isinstance(tr, bs4.element.Tag):
            count += 1
            tds = tr.find_all('td')
            list.append([tds[0].contents[0], tds[1].string, tds[3].string])

def printed(list, num):
    print('{0:^10}\t{1:{3}^10}\t{2:^10}'.format('排名', '高校', '分数', chr(12288)))
    for i in range(num):
        L = list[i]
        print('{0:^10}\t{1:{3}^10}\t{2:^10}'.format(L[0], L[1], L[2], chr(12288)))


def main():
    list = []
    url = 'http://www.zuihaodaxue.com/zuihaodaxuepaiming2017.html'
    num = int(input('请问要查询2017前多少名的高校呢:'))
    html = getedhtml(url)
    returned(html, list, num)
    printed(list, num)

main()
           

运行所写代码

排名    	    高校    	    分数    
    1     	   清华大学   	  94.0    
    2     	   北京大学   	  81.2    
    3     	   浙江大学   	  77.8    
    4     	  上海交通大学  	  77.5    
    5     	   复旦大学   	  71.1    
    6     	 中国科学技术大学 	  65.9    
    7     	   南京大学   	  65.3    
    8     	  华中科技大学  	  63.0    
    9     	   中山大学   	  62.7    
    10    	 哈尔滨工业大学  	  61.6    
    11    	   同济大学   	  60.8    
    12    	   东南大学   	  59.8    
    13    	   武汉大学   	  58.4    
    14    	 北京航空航天大学 	  58.3    
    15    	   南开大学   	  58.2    
    16    	   四川大学   	  57.4    
    16    	  西安交通大学  	  57.4    
    18    	   天津大学   	  56.2    
    19    	  华南理工大学  	  56.1    
    20    	  北京师范大学  	  55.1    

           

结果如下,成功拿到排名数据。