第一个简单但完整的爬虫实例

从今天开始学爬虫,现在就来分享一个简单完整(具有启发意义)的实例吧。文章结构如下:

  1. 爬虫问题描述
  2. requests库的使用
  3. beautifulsoup4库的使用
  4. 爬取软科中国大学排名

1 爬虫问题概述

   爬虫即(常用Python)从各个网站/页提取用户感兴趣的各类数据,并做进一步的信息挖掘的程序。爬虫程序实现的步骤主要为:①通过网络链接获取网页内容;②对获取的网页内容进行处理,这俩步骤分别使用requests与beautifulsoup4类库。网络爬虫实则包括:“网络爬虫”与“信息提交”。此外,网站的 “Robots排除协议”可以拒绝爬虫访问。

2 requests库的使用

  requests是一个简洁且简单的处理HTTP请求的第三方库。
import requests
def getHtmlText(url):
    try:
        res=requests.get(url,timeout=15) #超时15秒(url必为:http/https)
        res.raise_for_status() #如果返回状态不是200,引发异常
        res.encoding="utf-8" #使之正常显示中文
        return res.text #返回网页内容的字符串形式(res.content()二进制形式)
    except: '''①ConnectionError异常:DNS查询失败、拒接连接;②HTTPError异常:无效的http响应;③Timeout异常:请求超时;④TooManyRedirects异常:请求超过了设定的最大重定向次数'''
        return ""

3 beautifulsoup4库的使用

  beautifulsoup4是一个解析、处理HTML、XML的第三方库。获取HTML页面内容后,需进一步解析页面格式,提取有用信息。bs4最大的优势是:能根据HTML和XML语法建立解析树,进而高效地解析其中的内容。
  bs4采用面向对象思想实现:每一个实例便是一个页面;HTML页面标签(Tag)成为bs4对象的属性(“.”访问);每个Tag也是一个对象(“.”访问)。 层次为:【页面(soup)→Tag标签(head、title、a等)→标签属性(name、attrs、string、contents)→标签属性查找find_all()】
url="http://www.baidu.com"
soup=BeautifulSoup(getHtmlText(url)) #soup对象
print(soup.head) #<head>
print(soup.title) #<title>; type(soup.title):<class 'bs4.element.Tag'>
print(soup.p,soup.body,soup.strings,soup.stripped_strings)#<p>...【远不止这些】

soup_a=soup.a  #Tag对象
print("name:",soup_a.name) #Tag名(str)
print("attrs:",soup_a.attrs) #此Tag的所有属性(dict)
print("string:",soup_a.string) #Tag所夹文本→一般中文(str)【嵌一层,返里层;嵌多层,返None】
print("contents:",soup_a.contents) #此Tag下所有子Tag内容(list)

  同一页面可有多个同名标签,而单独“soup.Tag”仅能操控第一个标签,故需用find()或find_all()方法:soup.find_all(name,attrs,recursive,string,limit)→返回列表。①name:标签名、②attrs:Tag属性值(dict)、③recursive:查找层次(仅查找当前Tag下一层False)、④string:关键字检索string属性内容,采用string=开始、⑤limit:返回结果个数(默认全部)。备注:soup.find(name,attrs,recursive,string)→返回字符串(匹配的第一个!)。

tag_a=soup.find_all("a") #所有的构成列表
print(soup.find_all('a',{'href':'http://v.baidu.com'})) #查找特定一个
print(len(soup.find_all('a',{'href':re.compile('baidu.com')}))) #正则表达式“模糊匹配”
print(soup.find_all(string=re.compile('百度'))) #['百度一下,你就知道', '关于百度', '使用百度前必读']

4 爬取软科中国大学排名

  采用requests爬取网页内容,继而使用beautifulsoup4分析、提取网页中的数据,再储存至二维列表中,最后以用户偏好形式打印出。
import requests
from bs4 import BeautifulSoup #但并不是BeautifulSoup库

'''(1)抓取网页内容'''
def getHtmlText(url):
    try:
        res=requests.get(url,timeout=15) #超时15秒(url必为:http/https)
        res.raise_for_status() #如果返回状态不是200,则引发异常
        res.encoding="utf-8" #使之正常显示中文
        return res.text #返回网页内容的字符串形式(res.content()二进制形式)
    except:
        '''①ConnectionError异常:DNS查询失败、拒接连接;②HTTPError异常:无效的http响应;
        ③Timeout异常:请求超时;④TooManyRedirects异常:请求超过了设定的最大重定向次数'''
        return ""
    
'''(2)提取网页内容信息'''
'''请右键查看网页源码,以决定如何分割字符'''
def get_allData(soup):
    allSchoolData=list()
    trData=soup.find_all('tr') #页面所有的<tr></tr>
    for tr in trData:
        tdData=tr.find_all('td')
        if len(tdData)==0:  #去除非目的<tr>
            continue
        oneSchoolData=[] #一个<tr>有多个<td>
        for td in tdData:
            oneSchoolData.append(td.string) #某个<td>的string
        allSchoolData.append(oneSchoolData)
    return allSchoolData

'''(3)打印结果'''
def printResult(data):
    print("{:^4}{:^10}{:^5}{:^8}{:^10}".format("排名","学校名称","省市","总分","科研规模"))
    for i in range(len(data)):
        oneschool=data[i]
        '''打印什么数据:你得查看具体的网页'''
        print("{:^4}{:^10}{:^5}{:^8}{:^10}".format(oneschool[0],oneschool[1],oneschool[2],\
              oneschool[3],oneschool[6]))

'''主程序'''
if __name__=='main':
    url="http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html"
    soup=BeautifulSoup(getHtmlText(url)) #页面解析对象
    printResult(get_allData(soup)) #输出结果

  结果如下:
大学排名结果