功能描述
输入:大学排名URL连接
输出:大学排名信息的屏幕输出(排名,大学名称,总分)
技术路线:requests&bs4
定向爬虫:仅对输入url进行爬取,不扩展爬取
程序的结构设计:
- 从网络上获取大学排名网页内容
- 提取网页内容中信息到合适的数据结构
- 利用数据结构展示并输出结果
程序具体步骤讲解
第一步:
使用嵩天老师一直强调的通用代码框架,这个框架可以用在很多爬虫中用来获得HTML文本,并且它通过response.raise_for_status()方法判断返回的状态码是不是200,如果不是,就会引发HTTPerror异常,然后通过try&except的异常处理得到异常,而apparent_encoding则可以使得返回的编码准确。这样一个简单的通用代码框架可以有效地处理访问时遇到的网络问题。
第二步:
使用BeautifulSoup解析提取到的HTML文本,'html.parser’是python标准库作为解析器,刚才用浏览器已经看到我们所要提取的信息位置位于标签中,所以用for循环获取找到的所有孩子节点,然后用isinstance方法剔除掉一些不需要的信息,然后将tr中的td内容合成一个列表,最后将信息存入列表ulist中。
第三步:
将存放进列表中的信息格式化输出出来,这一步也可以用文件操作替换,后续很多练习会用到文件存放,这里还是使用format格式化输出的办法。
format的用法
- format的基本用法
(1)不带编号,即"{}"
(2)带数字编号,可调换顺序,即"{1}""{2}"
(3)带关键字,即"{a}""{tom}"
#不带编号
print('{} {}'.format('hello','world'))
#带数字编号,可调换顺序
print('{0} {1}'.format('hello','world'))
print('{1} {0}'.format('hello','world'))
#带关键字
print('{a} {tom} {a}'.format(a='hello',b='world'))
'''输出结果
hello world
hello world
world hello
hello world hello
'''
- 进阶用法
(1)<左对齐、>右对齐、^中间对齐、=在小数点后进行补齐(只用于数字)
(2)取位数"{:4s}" "{:.2f}"等
#默认左对齐
print('{} and {}'.format('hello','world'))
#取10位左对齐,取10位右对齐
print('{:<10s} and {:>10s}'.format('hello','world'))
#取10位居中对齐
print('{:^10s} and {:^10s}'.format('hello','world'))
#取两位小数
print('{:.2f}'.format(1.1234))
#取两位小数,右对齐取10位
print('{0}' is '{1:>10.2f}'.format(1.123,1.12))
'''
输出结果:
hello and world
hello and world
hello and world
1.120000
1.123 is 1.12
'''
“中国大学排名定向爬虫”实例
import requests
from bs4 import BeautifulSoup
import bs4
def getHTMLText(url)
try:
r=requests.get(url, timeout=30)
r.raise_for_status()
r.encoding=r.apparent_encoding
return r.text
except:
return""
def fillUnivList(ulist,html): #将HTML页面放入到一个新的列表中,列表名称定义为ulist
soup=BeautifulSoup(html,"html.parser")
for tr in soup.find('tbody').children: #对tbody标签下的孩子进行遍历
if isinstance(tr,bes.element.Tag): #过滤掉非标签类型的其他信息,如果不是bs4库中的tag类型,将被过滤
tds = tr('td') #在tr标签中找到td标签的信息
ulist.append([tds[0].string,tds[1].string,tds[2].string]) #将td标签中的排名、大学名称及分数等信息存储在ulist中
def printUnivList(ulist,num):
print('{:^10}\t{:^6}\t{:^10}'.format("排名","学校名称","总分")) #打印表头
for i in range (num):
u=ulist[i]
print("{:^10} {:^6} {:^10}".format(u[0],u[1],u[2]))
print("Suc"+str(num)) #输出大学的输出个数
def main():
uinfo =[] #将大学信息放到uinfo这个列表中
url = "http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html" #给出大学排名的url链接
#分别调取3个步骤所调用的函数
html=getHTMLText(url) #将url转换成html
fillUnivList(uinfo,html) #将html提取后放到uinfo的变量中
printUnivList(uinfo,20) #打印大学信息 / 20 universities
main()
输出结果:
进行实例优化
问题:中文字符对齐效果不好
中文对齐问题的原因:
解决方案:
采用中文字符空格填充chr(12288)
程序修改部分:
def printUnivList(ulist,num): #将ulist信息打印出来,num将列表中的多少个学校、多少个元素打印出来
tplt="{0:^10}\t{1:{3}^10}\t{2:^10}" #生成输出模板变量,{3}表示使用format的第三种变量进行填充
print(tplt.format("排名","学校名称","总分",chr(12288))) #表头用format来实现
for i in range(num):
u=ulist[i] #第i所大学用u代替
print(tplt.format(u[0],u[1],u[2],chr(12288))) #打印ulist中的排名、学校名称及总分的信息
print("Suc" + str(num))
修改后的输出结果:
完整版代码
import requests
from bs4 import BeautifulSoup
import bs4
def getHTMLText(url): #输入是需要获取的url信息,输出是url的内容
try:
r=requests.get(url,timeout=30) #获取url信息,设置timeout时间
r.raise_for_status() #产生异常信息,判断是否连接成功
r.encoding = r.apparent_encoding #修改编码
return r.text #网页信息返回给程序其他部分
except:
return "" #如果出现,错误返回空字符
def fillUnivList(ulist,html): #将HTML页面放入到一个新的列表中,列表名称定义为ulist
soup = BeautifulSoup(html,"html.parser")
for tr in soup.find('tbody').children: #url中大学信息在tbody标签中,查找body
if isinstance(tr,bs4.element.Tag): #过滤掉非标签类型的其他信息,如果不是bs4库中的tag类型,将被过滤掉
tds = tr('td') #tr的td标签存在tds
ulist.append([tds[0].string,tds[1].string,tds[2].string]) #将td标签中的大学名称、排名、分数等信息存储到ulist列表中
def printUnivList(ulist,num):#将ulist信息打印出来,num将列表中的多少个学校、多少个元素打印出来
tplt="{0:^10}\t{1:{3}^10}\t{2:^10}" #生成输出模板变量,{3}表示使用format的第3种变量进行填充
print(tplt.format("排名","学校名称","总分",chr(12288))) #表头用format来实现
for i in range(num):
u=ulist[i] #第i所大学用u代替
print(tplt.format(u[0],u[1],u[2],chr(12288))) #打印ulist中的排名、学校名称及总分的信息
print("Suc" + str(num))
def main():
uinfo =[] #将大学信息放到uinfo这个列表中
url = "http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html" #给出大学排名的url链接
#分别调取3个步骤所调用的函数
html=getHTMLText(url) #将url转换成html
fillUnivList(uinfo,html) #将html提取后放到uinfo的变量中
printUnivList(uinfo,20) #打印大学信息 / 20 universities
main()