说好的要从练习中学习爬虫的基础操作,所以就先从容易爬取的静态网页开始吧!
今天要爬取的是最好大学网上的2018年中国大学排名。我个人认为这个是刚接触爬虫时用来练习的一个很不错的网页了。
在说这个练习之前,给新着手学习爬虫的同学提供一个中国MOOC上北京理工大学嵩天老师的视频, Python网络爬虫与信息提取
今天这个练习便是出自嵩天老师的视频
运行平台:Windows
Python版本:Python3.6
IDE: Sublime Text Python自带IDLE
其他:Chrome浏览器
简述流程为:
步骤1:利用IDLE简单测试爬取的网页
步骤2:浏览器上查看网页信息
步骤3:从网页中获取HTML文本
步骤4:提取网页信息并存入合适的数据结构
步骤5:利用数据结构输出结果
首先我们可以用Python自带的IDLE来简单测试一下网页是否可访问
我们通过requests的get方法已经获得了网页的响应,通过返回的状态码200可以知道访问成功,随后用text方法来查看返回的HTML文档,这里要注意记得控制返回的Text文档大小,用切片的方法控制一下,否则很容易使得IDLE无响应。我们注意到返回的源码中有许多乱码,这是怎么回事呢?我们先查看一下网页的编码是什么,返回的‘ISO-8859-1’可以让我们知道该编码不支持中文显示,所以我们可以通过修改编码为‘utf-8’的方法成功取得可以显示中文的源码。当然我们还可以用robotparser模块查看网页的obots.txt文件,robots.txt文件是网页用来告诉我们哪些页面允许爬取,哪些页面不建议爬取,这并不是一个强制性约束的文件,不过在涉及到其他应用的时候,还是建议遵守文件。当然,我们这里只是用来练习,是没啥问题的,需要查看最好大学网的robots。txt文件也可以直接输入网址“ http://www.zuihaodaxue.cn/zuihaodaxuepaiming2018.html/robots.txt”,当然,你会看到404 Not Found,这表示这个网页没有robots.txt,相应的也就是默认可以爬取的,当然,爬取的时候需要控制好频率。
随后,我们打开Chrome浏览器,打开网页。
可以看到排名都在一个总的表格中,我们要爬取的学校以及总分排名等信息也都在其中。我们可以在清华大学点击鼠标右键,然后点击检查,看看网页返回了什么。
可以在下方看到(也有可能出现在右方,这个可以自己设置,下方这个新出的区域的右上角有三个竖着的点,点击就可以设置了)清华大学,北京,95.3等大学信息都在标签
的子标签
第一步就是使用嵩天老师一直强调的通用代码框架了,这个框架可以用在很多爬虫中用来获取HTML文本,并且它通过response.raise_for_status()方法判断返回的状态码是不是200,如果不是,就会引发HTTPError异常,然后通过try except的异常处理获取到异常,而apparent_encoding则可以使得返回的编码准确。这样一个简单的通用代码框架可以有效的处理访问处理时遇到的网络问题。
第二步则是用BeautifulSoup解析提取到的HTML文本,'html.parser'是Python标准库作为解析器,刚才用浏览器已经看到我们所要提取的信息位置位于标签
第三步则是将存入列表中的信息格式化输出出来,这一步也可以用文件操作替换,后续很多练习会用到文件存放。这里还是使用format格式化输出的办法。首先来理解一下tplt这个字符串的结构,如图所示:
关于format的其他用法,比如填充对齐,精度控制等大家有兴趣可以百度一下啦。关于chr(12288)则是嵩天老师在优化中文对齐时提到的,因为中文字符对齐与英文字符对齐的宽度不一样,所以用chr(12288)使得采用中文字符的空格对齐。
然后就是使用format输出列表中的文本了。这里还用到了range 来控制输出的大学数。
最后我们看下输出结果,这里只输出了排名前20的大学。
源码的话,由于代码不长,就直接文本放出来吧
'''
利用requests+BeautifulSoup爬取最好大学网中2018年中国大学排名
'''
import requests
from bs4 import BeautifulSoup
import bs4
def get_one_page(url):
try:
response = requests.get(url,timeout=30)
response.raise_for_status()
response.encoding = response.apparent_encoding
return response.text
except:
print("产生异常")
return ""
def parse_one_page(ulist,html):
soup = BeautifulSoup(html,'html.parser')
for tr in soup.find('tbody').children:
if isinstance(tr,bs4.element.Tag):
tds = tr('td')
ulist.append([tds[0].string,tds[1].string,tds[2].string,tds[3].string])
def print_one_page(ulist,num):
tplt = "{0:^10}\t{1:{4}^10}\t{2:{4}^10}\t{3:^10}"
print(tplt.format("排名","学校名称","学校地址","总分",chr(12288)))
for i in range(num):
u = ulist[i]
print(tplt.format(u[0],u[1],u[2],u[3],chr(12288)))
def main():
uinfo = []
url = 'http://www.zuihaodaxue.cn/zuihaodaxuepaiming2018.html'
html = get_one_page(url)
parse_one_page(uinfo,html)
print_one_page(uinfo,20)
if __name__ == '__main__':
main()
好啦,今天的练习就到此结束了,应该写得还是挺详细的吧(emmmmm)。希望大家能够有所收获咯,当然,大神还是绕路吧,小白瑟瑟发抖。如果有错误的地方,请大家多多指教。