前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python:使用爬虫获取中国最好的大学排名数据(爬虫入门)

Python:使用爬虫获取中国最好的大学排名数据(爬虫入门)

作者头像
wsuo
发布2020-07-30 18:52:54
1.7K0
发布2020-07-30 18:52:54
举报
文章被收录于专栏:技术进阶之路

文章目录
  • 问题描述
  • 结果展示
  • 解决思路
  • 代码实现
  • 代码讲解
  • 总结一下
  • 使用 XPath 实现

问题描述

请使用 Python 爬取最好大学网大学排名数据 ,并保存为 CSV 和 Excel 格式。

结果展示

以爬取前 10 名大学为例:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

解决思路

目标网站:软科中国最好大学排名2019 使用 Python 的 BeautifulSoup 库:BeautifulSoup官方文档

这里主要使用了 BeautifulSoup 库,该库功能十分强大,我只使用了它不到 1% 的功能。更多的功能请大家看官方文档,是中文的哦。

因为是使用爬虫,所以必须引入的两个库是:requestsBeautifulSoup,另外设计存储到 Excel 中,所以我选择使用 pandas 库,它的二维结构提供很方便的方法可以直接存储到 Excel 中,另外用到pandas就会用到numpy用来生成二维数组。

所以用到的库有:

  • ? requests
  • ? bs4
  • ? pandas
  • ? numpy

代码实现

代码语言:javascript
复制
import requests as rq
from bs4 import BeautifulSoup as Bs
import pandas as pd
import numpy as np

def getData(resLoc):
    rp = rq.get(resLoc)
    rp.encoding = 'utf-8'
    return rp.text

def dataProcessing(html, num):
    table = Bs(html, features='lxml').table.find_all('tr', limit=num, recursive=True)
    table_head = table[0]
    universityList = []
    for tr in table[1:]:
        tds = tr.find_all('td')
        contents = [td.contents for td in tds]
        contents[1] = contents[1][0].contents
        universityList.append(contents)
    thf = [th.contents for th in table_head.find_all('th', limit=4)]
    for i in [op.contents for op in table_head.find_all('option', recursive=True)]:
        thf.append(i)
    thf = ["".join(th) for th in thf]
    univList = []
    for university in universityList:
        university = ["".join(attr) for attr in university]
        univList.append(university)

    return pd.DataFrame(np.array(univList), columns=thf)

def saveData(data):
    data.to_csv('university.csv', index=False)
    data.to_excel('university.xlsx', index=False)

def main(num):
    if num >= 549:
        return
    else:
        url = 'http://zuihaodaxue.com/zuihaodaxuepaiming2019.html'
        saveData(dataProcessing(getData(url), num + 1))

# 测试,爬取前 10 名大学的信息
main(10)

但是,相信大家看了上面的代码肯定想杀人,这代码的可读性几乎为0,根本不是写给人看的,所以下面我们讲解一下代码。

代码讲解

下面我采用注释的方式带大家一步一步的来解决这个问题,并且可以学到很多知识。

首先我们先导包:

代码语言:javascript
复制
import requests as rq
from bs4 import BeautifulSoup as Bs
import pandas as pd
import numpy as np

我们使用的 BeautifulSoupbs4 中的一个类,所以我们引入该类就可以了,顺便起一个别名。

但是这个库实际上是叫做 beautifulsoup的,我们 install 的时候也是安装的 beautifulsoup ,但是执行的导包的时候是 bs4

这里我们以一种自顶向下的思维编程,具体就是,先列出函数,函数具体怎么执行的我先不管,我只要你的返回值,然后我拿来使用。

所以我们先在 main 方法中定义一些函数,之后再实现。

代码语言:javascript
复制
def main(num):
    # 由于该网站最多有550个大学,所以输入的数字不能大于550,否则什么也不做
    if num >= 550:
        print("数量不能大于550")
        return
    else:
        url = 'http://zuihaodaxue.com/zuihaodaxuepaiming2019.html'
        # 获取数据
        text = getData(url)
        # 处理数据, num 是你要爬取前多少名大学的排名信息
        universityList = dataProcessing(text, num + 1)
        # 保存数据
        saveData(universityList)
        print("文件保存成功!")

我们打开这个网站来看一下:

在这里插入图片描述
在这里插入图片描述

习惯上我们使用 F12 打开,也可以右键表格,点击检查:

在这里插入图片描述
在这里插入图片描述

我们需要的数据就在这里面:

在这里插入图片描述
在这里插入图片描述

每一个 tr 里面都有一行数据,这就是我们想要的,而表头就是标题,我们后面都会用到。

在这里插入图片描述
在这里插入图片描述

现在我们一个一个的实现这些函数:

首先是 getData(url) 方法,该方法就是通过程序获取我们在浏览器看到的 Html 页面。

代码语言:javascript
复制
# 获取数据,就是通过访问网页,把他的html源代码拿过来
def getData(resLoc):
    rp = rq.get(resLoc)
    rp.encoding = 'utf-8'
    return rp.text

get 表示是 GET 请求,encoding 设置编码。

好了,获取了数据,我们就要分割处理数据了。

就是 dataProcessing(html, num) 方法,num 是爬取的大学数量。

首先创建一个 BeautifulSoup 对象:

代码语言:javascript
复制
bs = Bs(html, features='lxml')

然后呢,这个 bs 其实代表是整个 HTML 的 DOM 树,我们要做的就是从这个 DOM 树中取东西。

我们之前已经看过 HTML 的格式了,他只有一个 table 标签,所以我们可以通过点的方式获取这个 table 元素。

然后他返回的还是一个 bs 对象,只不过这个 DOM 树变小了,所以我们可以使用 find_all 方法来获取 table 下的所有 tr标签。

代码语言:javascript
复制
# 包含表头的列表
table = bs.table.find_all('tr', limit=num, recursive=True)

但是这里是有问题的,因为这张表有表头,表头的 tr我们需要单独拿出来。

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
table_head = table[0]
print(table_head)

我们打印出来看一下表头是啥:

代码语言:javascript
复制
	# 看一下表头是什么:
    # <tr>
    #   <th style="text-align: center;">排名</th>
    #   <th style="text-align: center;">学校名称</th>
    #   <th class="hidden-xs" style="text-align: center; width: 80px;">省市</th>
    #   <th style="text-align: center;">总分</th>
    #   <th class="hidden-xs" style="text-align: center; width: 265px;">指标得分<br/>
    #   <select class="form-control" id="select-indicator-type" name="type" style="text-align: left;">
    #     <option selected="selected" title="生源质量(新生高考成绩得分)" value="indicator5">生源质量(新生高考成绩得分)</option>
    #     <option title="培养结果(毕业生就业率)" value="indicator6">培养结果(毕业生就业率)</option>
    #     <option title="社会声誉(社会捐赠收入·千元)" value="indicator7">社会声誉(社会捐赠收入·千元)</option>
    #     <option title="科研规模(论文数量·篇)" value="indicator8">科研规模(论文数量·篇)</option>
    #     <option title="科研质量(论文质量·FWCI)" value="indicator9">科研质量(论文质量·FWCI)</option>
    #     <option title="顶尖成果(高被引论文·篇)" value="indicator10">顶尖成果(高被引论文·篇)</option>
    #     <option title="顶尖人才(高被引学者·人)" value="indicator11">顶尖人才(高被引学者·人)</option>
    #     <option title="科技服务(企业科研经费·千元)" value="indicator12">科技服务(企业科研经费·千元)</option>
    #     <option title="成果转化(技术转让收入·千元)" value="indicator13">成果转化(技术转让收入·千元)</option>
    #     <option title="学生国际化(留学生比例) " value="indicator14">学生国际化(留学生比例)</option>
    #   </select>
    #   </th>
    # </tr>

这正是我们想要的数据,我们可以通过 contents 获取 标签对 里面的数据,就大功告成了。

代码语言:javascript
复制
# 这里为什么只要四个呢? 因为第五个是下拉选框,我们后面再单独处理
ths = table_head.find_all('th', limit=4)
# 这里是表头的前四个元素 [['排名'], ['学校名称'], ['省市'], ['总分']], th_four 代表前四个th
thf = [th.contents for th in ths]

在仔细看你会发现后面有一个不是普通的列表,他是一个 select!所以我们上面只要了前四个。

在这里插入图片描述
在这里插入图片描述

下面处理下拉框中的元素 option

代码语言:javascript
复制
options = [op.contents for op in table_head.find_all('option', recursive=True)]

打印出来看看:

代码语言:javascript
复制
	# [ ['生源质量(新生高考成绩得分)'],
    #   ['培养结果(毕业生就业率)'],
    #   ['社会声誉(社会捐赠收入·千元)'],
    #   ['科研规模(论文数量·篇)'],
    #   ['科研质量(论文质量·FWCI)'],
    #   ['顶尖成果(高被引论文·篇)'],
    #   ['顶尖人才(高被引学者·人)'],
    #   ['科技服务(企业科研经费·千元)'],
    #   ['成果转化(技术转让收入·千元)'],
    #   ['学生国际化(留学生比例)'] ]

正是我们想要的,不过他是二维列表,不怕后面我们再处理。

将这个和之前的 4 个合并。

代码语言:javascript
复制
for i in options:
	thf.append(i)

现在我们处理表体,也就是最最干货的内容。

代码语言:javascript
复制
# 去掉表头,只要表体
table_body = table[1:]

打印出来看一下每一条 tr 里面是什么?

代码语言:javascript
复制
	# [ <tr class="alt">
    #   <td>1</td> --排名
    #   <td><div align="left">清华大学</div></td> --学校名称
    #   <td>北京</td> --省市
    #   <td>94.6</td> --总分
    #   <td class="hidden-xs need-hidden indicator5">100.0</td> --生源质量
    #   <td class="hidden-xs need-hidden indicator6" style="display: none;">98.30%</td> --培养结果
    #   <td class="hidden-xs need-hidden indicator7" style="display: none;">1589319</td> --社会声誉
    #   <td class="hidden-xs need-hidden indicator8" style="display: none;">48698</td> --科研规模
    #   <td class="hidden-xs need-hidden indicator9" style="display: none;">1.512</td> --科研质量
    #   <td class="hidden-xs need-hidden indicator10" style="display: none;">1810</td> --顶尖成果
    #   <td class="hidden-xs need-hidden indicator11" style="display: none;">126</td> --顶尖人才
    #   <td class="hidden-xs need-hidden indicator12" style="display: none;">1697330</td> --科技服务
    #   <td class="hidden-xs need-hidden indicator13" style="display: none;">302898</td> --成果转化
    #   <td class="hidden-xs need-hidden indicator14" style="display: none;">6.81%</td> --学生国际化
    # </tr> ]

我们可以无视上面标签中的属性值,只关注内容,也就是说对于table_body中的每一个tr标签,我们要做的是取出来其中的td中的content,作为二维列表。

编写一个循环来遍历每一个 tr

代码语言:javascript
复制
universityList = []
for tr in table_body:
    tds = tr.find_all('td')

这个时候我们打印一下tds看看:

代码语言:javascript
复制
		# tds 的结果是:
        # print(tds)
        # [ <td>1</td>,
        #   <td><div align="left">清华大学</div></td>,
        #   <td>北京</td>, <td>94.6</td>,
        #   <td class="hidden-xs need-hidden indicator5">100.0</td>,
        #   <td class="hidden-xs need-hidden indicator6" style="display: none;">98.30%</td>,
        #   <td class="hidden-xs need-hidden indicator7" style="display: none;">1589319</td>,
        #   <td class="hidden-xs need-hidden indicator8" style="display: none;">48698</td>,
        #   <td class="hidden-xs need-hidden indicator9" style="display: none;">1.512</td>,
        #   <td class="hidden-xs need-hidden indicator10" style="display: none;">1810</td>,
        #   <td class="hidden-xs need-hidden indicator11" style="display: none;">126</td>,
        #   <td class="hidden-xs need-hidden indicator12" style="display: none;">1697330</td>,
        #   <td class="hidden-xs need-hidden indicator13" style="display: none;">302898</td>,
        #   <td class="hidden-xs need-hidden indicator14" style="display: none;">6.81%</td> ]

可以看到是一个列表,我们获取每一个 td 标签的 content

代码语言:javascript
复制
contents = [td.contents for td in tds]
代码语言:javascript
复制
		# for td in tds:
        #     print(td.contents)
        # 得到的结果如下:
        # ['1']
        # [<div align="left">清华大学</div>]
        # ['北京']
        # ['94.6']
        # ['100.0']
        # ['98.30%']
        # ['1589319']
        # ['48698']
        # ['1.512']
        # ['1810']
        # ['126']
        # ['1697330']
        # ['302898']
        # ['6.81%']

但是有一个问题就是 [<div align="left">清华大学</div>] 这里有一个 div 标签,我们要把它替换成他里面的元素值。

代码语言:javascript
复制
contents[1] = contents[1][0].contents

大家注意我们现在还在for循环当中哦,我们要这些遍历到的contents存到外面的变量中才能保存起来

代码语言:javascript
复制
universityList.append(contents)

现在我们得到的列表就是类似于这种形式[[[清华], [1], ...], [[北大], [2], ...], ...]

降维打击!

代码语言:javascript
复制
# 下面的问题是, 我们有了表头列表 thf(二维),有了表体列表 universityList(三维), 怎么把它们合并呢?
# thf: [['排名'], ['学校名称'], ['省市'], ['总分'], ['生源质量(新生高考成绩得分)'], ['培养结果(毕业生就业率)'], ['社会声誉(社会捐赠收入·千元)'], ['科研规模(论文数量·篇)'], ['科研质量(论文质量·FWCI)'], ['顶尖成果(高被引论文·篇)'], ['顶尖人才(高被引学者·人)'], ['科技服务(企业科研经费·千元)'], ['成果转化(技术转让收入·千元)'], ['学生国际化(留学生比例)']]
# universityList: [
#                   [['1'], ['清华大学'], ['北京'], ['94.6'], ['100.0'], ['98.30%'], ['1589319'], ['48698'], ['1.512'], ['1810'], ['126'], ['1697330'], ['302898'], ['6.81%']],
#                   [['2'], ['北京大学'], ['北京'], ['76.5'], ['95.2'], ['98.07%'], ['570497'], ['47161'], ['1.409'], ['1402'], ['100'], ['554680'], ['14445'], ['6.15%']]
#                 ]

我们使用 DataFrame配合 numpy 可以实现这个功能,因为DataFrame有一个功能就是可以将几行和一列数据一一对应形成一个表格。

代码语言:javascript
复制
# 但是还有一个问题就是DataFrame是二维结构,我们这里是三维结构,显然需要降维打击!
# 我们把最里面的列表可以转化为字符串,实现降维
代码语言:javascript
复制
# 降维的过程
thf = ["".join(th) for th in thf]
univList = []
for university in universityList:
    university = ["".join(attr) for attr in university]
    univList.append(university)
    
# 下面使用 DataFrame 的构造函数,传入一个 numpy 构造的数组和一个列表作为表头
pd_universityList = pd.DataFrame(np.array(univList), columns=thf)

return pd_universityList

上面的代码值得一提的就是这一个pd.DataFrame(np.array(univList), columns=thf),这里先是传入了一个二维数组,然后第二个参数columns指的就是表头,也就是说他会形成一种一一对应的关系,columns的每一个元素,对应二维数组的每一个元素的对应元素。

比如说我们的二维数组是:

代码语言:javascript
复制
1,清华大学,北京
2,北京大学,北京

那么columns对应的就是排名,学校名称,省市,他会自动将排名和1,2对应,学校和清华大学对应。

在调试的过程中可能 DataFrame 显示不全,可以采用下面的方法显示全。

代码语言:javascript
复制
# 显示所有列
# pd.set_option('display.max_columns', None)
# 显示所有行
# pd.set_option('display.max_rows', None)
# 设置value的显示长度为100,默认为50
# pd.set_option('max_colwidth', 100)
# print(pd_universityList)

到此为止,我们最重要的方法就介绍完了,下面我们编写第三个函数吧。

代码语言:javascript
复制
# 负责保存数据到本地磁盘
def saveData(data):
    data.to_csv('university.csv', index=False)
    data.to_excel('university.xlsx', index=False)

这里直接使用DataFrame自带的方法就可以实现保存到本地。

好了,全部都做完了,下面我们只需要调用一下主函数即可运行程序。

输入几就可以获取前几名大学的数据,但是不能超过550,因为那网页上就只有549个 。

代码语言:javascript
复制
# 测试,爬取前10名大学的信息
main(10)
在这里插入图片描述
在这里插入图片描述

带注释的代码展示:

代码语言:javascript
复制
"""
@author: shoo Wang
@contact: wangsuoo@foxmail.com
@file: demo02.py
@time: 2020/5/6 0006
"""
import requests as rq
from bs4 import BeautifulSoup as Bs
import pandas as pd
import numpy as np


# 获取数据,就是通过访问网页,把他的html源代码拿过来
def getData(resLoc):
    rp = rq.get(resLoc)
    rp.encoding = 'utf-8'
    return rp.text


# 最关键的部分: 数据处理,我们的目标是将文本格式的 html 网页转化为表格的形式;
def dataProcessing(html, num):
    bs = Bs(html, features='lxml')
    # 包含表头的列表
    table = bs.table.find_all('tr', limit=num, recursive=True)
    table_head = table[0]
    # print(table_head)
    # 看一下表头是什么:
    # <tr>
    #   <th style="text-align: center;">排名</th>
    #   <th style="text-align: center;">学校名称</th>
    #   <th class="hidden-xs" style="text-align: center; width: 80px;">省市</th>
    #   <th style="text-align: center;">总分</th>
    #   <th class="hidden-xs" style="text-align: center; width: 265px;">指标得分<br/>
    #   <select class="form-control" id="select-indicator-type" name="type" style="text-align: left;">
    #     <option selected="selected" title="生源质量(新生高考成绩得分)" value="indicator5">生源质量(新生高考成绩得分)</option>
    #     <option title="培养结果(毕业生就业率)" value="indicator6">培养结果(毕业生就业率)</option>
    #     <option title="社会声誉(社会捐赠收入·千元)" value="indicator7">社会声誉(社会捐赠收入·千元)</option>
    #     <option title="科研规模(论文数量·篇)" value="indicator8">科研规模(论文数量·篇)</option>
    #     <option title="科研质量(论文质量·FWCI)" value="indicator9">科研质量(论文质量·FWCI)</option>
    #     <option title="顶尖成果(高被引论文·篇)" value="indicator10">顶尖成果(高被引论文·篇)</option>
    #     <option title="顶尖人才(高被引学者·人)" value="indicator11">顶尖人才(高被引学者·人)</option>
    #     <option title="科技服务(企业科研经费·千元)" value="indicator12">科技服务(企业科研经费·千元)</option>
    #     <option title="成果转化(技术转让收入·千元)" value="indicator13">成果转化(技术转让收入·千元)</option>
    #     <option title="学生国际化(留学生比例) " value="indicator14">学生国际化(留学生比例)</option>
    #   </select>
    #   </th>
    # </tr>
    # 去掉表头,只要表体
    table_body = table[1:]
    # print(table_body)
    # 看一下每一条 tr 里面是什么?
    # [ <tr class="alt">
    #   <td>1</td> --排名
    #   <td><div align="left">清华大学</div></td> --学校名称
    #   <td>北京</td> --省市
    #   <td>94.6</td> --总分
    #   <td class="hidden-xs need-hidden indicator5">100.0</td> --生源质量
    #   <td class="hidden-xs need-hidden indicator6" style="display: none;">98.30%</td> --培养结果
    #   <td class="hidden-xs need-hidden indicator7" style="display: none;">1589319</td> --社会声誉
    #   <td class="hidden-xs need-hidden indicator8" style="display: none;">48698</td> --科研规模
    #   <td class="hidden-xs need-hidden indicator9" style="display: none;">1.512</td> --科研质量
    #   <td class="hidden-xs need-hidden indicator10" style="display: none;">1810</td> --顶尖成果
    #   <td class="hidden-xs need-hidden indicator11" style="display: none;">126</td> --顶尖人才
    #   <td class="hidden-xs need-hidden indicator12" style="display: none;">1697330</td> --科技服务
    #   <td class="hidden-xs need-hidden indicator13" style="display: none;">302898</td> --成果转化
    #   <td class="hidden-xs need-hidden indicator14" style="display: none;">6.81%</td> --学生国际化
    # </tr> ]
    # for tr in table_body:
    # 我们可以无视上面标签中的属性值,只关注内容
    # 也就是说对于table_body中的每一个tr标签,我们要做的是取出来其中的td中的content,作为二维列表
    universityList = []
    for tr in table_body:
        tds = tr.find_all('td')
        # tds 的结果是:
        # print(tds)
        # [ <td>1</td>,
        #   <td><div align="left">清华大学</div></td>,
        #   <td>北京</td>, <td>94.6</td>,
        #   <td class="hidden-xs need-hidden indicator5">100.0</td>,
        #   <td class="hidden-xs need-hidden indicator6" style="display: none;">98.30%</td>,
        #   <td class="hidden-xs need-hidden indicator7" style="display: none;">1589319</td>,
        #   <td class="hidden-xs need-hidden indicator8" style="display: none;">48698</td>,
        #   <td class="hidden-xs need-hidden indicator9" style="display: none;">1.512</td>,
        #   <td class="hidden-xs need-hidden indicator10" style="display: none;">1810</td>,
        #   <td class="hidden-xs need-hidden indicator11" style="display: none;">126</td>,
        #   <td class="hidden-xs need-hidden indicator12" style="display: none;">1697330</td>,
        #   <td class="hidden-xs need-hidden indicator13" style="display: none;">302898</td>,
        #   <td class="hidden-xs need-hidden indicator14" style="display: none;">6.81%</td> ]
        # 可以看到是一个列表,我们获取每一个 td 标签的 content
        contents = [td.contents for td in tds]
        # for td in tds:
        #     print(td.contents)
        # 得到的结果如下:
        # ['1']
        # [<div align="left">清华大学</div>]
        # ['北京']
        # ['94.6']
        # ['100.0']
        # ['98.30%']
        # ['1589319']
        # ['48698']
        # ['1.512']
        # ['1810']
        # ['126']
        # ['1697330']
        # ['302898']
        # ['6.81%']
        # 但是有一个问题就是 [<div align="left">清华大学</div>] 这里有一个 div 标签,我们要把它替换成他里面的元素值
        contents[1] = contents[1][0].contents
        # 大家注意我们现在还在for循环当中哦,我们要这些遍历到的contents存到外面的变量中才能保存起来
        universityList.append(contents)

    # 现在我们得到的列表就是类似于这种形式[[[清华], [1], ...], [[北大], [2], ...], ...]
    # print(universityList)
    # 但是现在还没有把表头加上,现在我们加上表头,但是表头还是那个乱七八糟的形式,所以我们要先处理一下

    # 这里为什么只要四个呢? 因为第五个是下拉选框,我们后面再单独处理
    ths = table_head.find_all('th', limit=4)
    # 这里是表头的前四个元素 [['排名'], ['学校名称'], ['省市'], ['总分']], th_four 代表前四个th
    thf = [th.contents for th in ths]
    # 下面处理下拉框中的元素 option
    options = [op.contents for op in table_head.find_all('option', recursive=True)]
    # print(options)
    # [ ['生源质量(新生高考成绩得分)'],
    #   ['培养结果(毕业生就业率)'],
    #   ['社会声誉(社会捐赠收入·千元)'],
    #   ['科研规模(论文数量·篇)'],
    #   ['科研质量(论文质量·FWCI)'],
    #   ['顶尖成果(高被引论文·篇)'],
    #   ['顶尖人才(高被引学者·人)'],
    #   ['科技服务(企业科研经费·千元)'],
    #   ['成果转化(技术转让收入·千元)'],
    #   ['学生国际化(留学生比例)'] ]

    # 好了,现在我们合并表头
    for i in options:
        thf.append(i)
    # print(thf)
    # 下面的问题是, 我们有了表头列表 thf(二维),有了表体列表 universityList(三维), 怎么把它们合并呢?
    # thf: [['排名'], ['学校名称'], ['省市'], ['总分'], ['生源质量(新生高考成绩得分)'], ['培养结果(毕业生就业率)'], ['社会声誉(社会捐赠收入·千元)'], ['科研规模(论文数量·篇)'], ['科研质量(论文质量·FWCI)'], ['顶尖成果(高被引论文·篇)'], ['顶尖人才(高被引学者·人)'], ['科技服务(企业科研经费·千元)'], ['成果转化(技术转让收入·千元)'], ['学生国际化(留学生比例)']]
    # universityList: [
    #                   [['1'], ['清华大学'], ['北京'], ['94.6'], ['100.0'], ['98.30%'], ['1589319'], ['48698'], ['1.512'], ['1810'], ['126'], ['1697330'], ['302898'], ['6.81%']],
    #                   [['2'], ['北京大学'], ['北京'], ['76.5'], ['95.2'], ['98.07%'], ['570497'], ['47161'], ['1.409'], ['1402'], ['100'], ['554680'], ['14445'], ['6.15%']]
    #                 ]
    # 但是还有一个问题就是DataFrame是二维结构,我们这里是三维结构,显然需要降维打击!
    # 我们把最里面的列表可以转化为字符串,实现降维
    thf = ["".join(th) for th in thf]
    # universityList = ["".join(attr) for attr in [university for university in universityList]]
    # print(universityList)|
    univList = []
    for university in universityList:
        university = ["".join(attr) for attr in university]
        univList.append(university)

    pd_universityList = pd.DataFrame(np.array(univList), columns=thf)

    return pd_universityList
    # 显示所有列
    # pd.set_option('display.max_columns', None)
    # 显示所有行
    # pd.set_option('display.max_rows', None)
    # 设置value的显示长度为100,默认为50
    # pd.set_option('max_colwidth', 100)
    # print(pd_universityList)


# 负责保存数据到本地磁盘
def saveData(data):
    data.to_csv('university.csv', index=False)
    data.to_excel('university.xlsx', index=False)


def main(num):
    # 由于该网站最多有550个大学,所以输入的数字不能大于550,否则什么也不做
    if num >= 550:
        print("数量不能大于550")
        return
    else:
        url = 'http://zuihaodaxue.com/zuihaodaxuepaiming2019.html'
        # 获取数据
        text = getData(url)
        # 处理数据, num 是你要爬取前多少名大学的排名信息
        universityList = dataProcessing(text, num + 1)
        # 保存数据
        saveData(universityList)
        print("文件保存成功!")


# 测试,爬取前10名大学的信息
main(10)

总结一下

在这里插入图片描述
在这里插入图片描述

最重要的还是看 文档,我这里只用了一个方法就是find_all,他还有非常多强大的功能,我们只需要会使用就行了,我太 CAI 了,只是一个 API 选手,你敢信就这几行代码我扣了俩小时才写出来?,还是得更努力的学,虽然学到最后还只是一个 API 调用者。

会这一个方法就可以爬一些网站的数据了,其他的也是以此类推,只需要分析另一个网页的 DOM 结构即可,所以方法是通用的,如果你也是初学,不妨使用这个项目练练手。

使用 XPath 实现

http://www.zuihaodaxue.cn/网站中爬虫数据,获取中国大学排名(Top10)

  • 爬取的数据保存为CSV文件(.CSV)
  • 采用xpath语法提取数据
代码语言:javascript
复制
"""
@author: shoo Wang
@contact: wangsuoo@foxmail.com
@file: demo01.py
@time: 2020/5/11 0011
"""
import requests as rq
from lxml import etree
import pandas as pd
import numpy as np


# 获取数据,就是通过访问网页,把他的html源代码拿过来
def getData(resLoc):
    rp = rq.get(resLoc)
    rp.encoding = 'utf-8'
    return rp.text


# 最关键的部分: 数据处理,我们的目标是将文本格式的 html 网页转化为表格的形式;
def dataProcessing(html, num):
    html = etree.HTML(html)

    # 获取表头 //thead//th[position() < 5] //thead//option
    th = html.xpath('//thead//th[position() < 5]/text()')
    th_select = html.xpath('//thead//option/text()')
    th.extend(th_select)

    # 大学名称
    univ = html.xpath('//tbody/tr/td/div/text()')[:num]

    # //tbody/tr[1]/td/text() 获取每一条记录的数值
    nums = [[j for j in html.xpath('//tbody/tr[' + str(i + 1) + ']/td/text()')] for i in range(num)]
    idx = 0
    for num in nums:
        num.insert(1, univ[idx])
        idx += 1

    # 转化为 DataFrame 结构,因为这种结构很好转化为 Excel
    pd_universityList = pd.DataFrame(np.array(nums), columns=th)
    return pd_universityList


# 负责保存数据到本地磁盘
def saveData(data):
    data.to_csv('university_china.csv', index=False)


def main(num):
    # 由于该网站最多有 1000 个大学,所以输入的数字不能大于 1000 ,否则什么也不做
    if num >= 1000:
        print("数量不能大于1000")
        return
    else:
        url = 'http://zuihaodaxue.com/zuihaodaxuepaiming2019.html'
        universityList = dataProcessing(getData(url), num)
        saveData(universityList)
        print("文件保存成功!")


# 测试,爬取前10名大学的信息
main(10)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/05/06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 问题描述
  • 结果展示
  • 解决思路
  • 代码实现
  • 代码讲解
  • 总结一下
  • 使用 XPath 实现
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档