Beautiful Soup基础入门

Beautiful Soup基础入门



  • Requests 库
  • 遍历文档树
  • 搜索文档树
  • 标签基本元素
  • Beautiful Soup 库解析器

一、Beautiful Soup简介

就是一个可以从HTML或XML文件中提取数据的Python库。实例:在最好大学网爬取2021年软科类世界大学排名的数据。

二、基本步骤

用chrome浏览器去访问该网站,然后审查元素,定位相关信息对应的代码。整个实验的关键就在于如何遍历tbody标签的孩子标签,获取tr标签里的td标签的数据。

确定好之后,接下来使用requests.get()来获取整个页面的内容。用import requests来导入Requests库。

1、准备工作
import requests

r = requests.get("https://labfile.oss.aliyuncs.com/courses/2184/2019%E8%BD%AF%E7%A7%91%E4%B8%96%E7%95%8C%E5%A4%A7%E5%AD%A6%E5%AD%A6%E6%9C%AF%E6%8E%92%E5%90%8D.html")
print(r.status_code)  #检查状态码
#200
print(r.encoding)   #检查编码方式
#ISO-8859-1
r.encoding = r.apparent_encoding   #修改编码
print(r.encoding)
#utf-8
2、获取相应信息

r.text #获取整个页面内容

r.headers #获取页面头信息

html = r.text
print(html)
#输出html代码
header = r.headers
print(header)
'''
{'Server': 'AliyunOSS', 'Date': 'Thu, 29 Apr 2021 12:38:13 GMT', 'Content-Type': 'text/html', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'x-oss-request-id': '608AA8B555A1A637340A18C1', 'Last-Modified': 'Fri, 24 Apr 2020 08:55:54 GMT', 'x-oss-object-type': 'Normal', 'x-oss-hash-crc64ecma': '15463410703954662493', 'x-oss-storage-class': 'Standard', 'Cache-Control': 'no-cache', 'Content-MD5': 'UT34YnbEGFbQ5LT+UwuhyA==', 'x-oss-server-time': '15', 'Content-Encoding': 'gzip'}
'''
3、解析HTML页面

Beautiful Soup库有专门的解析器,解析器的作用简单来说,就是用来解析和提取HTML或XML页面的数据。它有四种解析器:

第一种Python自带,后三种需自行安装

python标准库

lxml HTML解析器

lxml XML 解析器

html5lib

下面使用python标准库的解析器,使用 from bs4 import BeautifulSoup 导入 BeautifulSoup 库。使用 BeautifulSoup(markup, "html.parser") 去解析页面。

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, "html.parser")
print(soup)
#返回有格式的html代码
4、遍历和搜索文档树

3-3 html 标签树

每个标签都有一个名字,每个标签可以有0个或者多个属性,标签之间的字符串是非属性字符串或者注释,如下图所示:

图 3-4 标签的基本元素

我们的实验任务是要获取页面上的三类数据,分别是学校排名、学校名字和学校总分。所以,我们需要遍历标签树,搜索到这三类数据并保存到列表中。从上面的内容我们已经知道,所需要的数据是在 tbody 的子标签里,所以我们需要使用 find() 去遍历 tbody 标签的孩子标签。

data = soup.find("tbody").children
print(data)
#输出tbody标签的子节点(是一个迭代器)

上面的代码中,find() 是搜索文档树中的一种方法,它能够返回第一个匹配的元素。它的完整参数形式为:find( name , attrs , recursive , string , **kwargs )。参数 name 是用标签名去检索字符串,参数 attrs 是用标签属性值去检索字符串,参数 recursive 是否对子孙全部检索,默认为 True,参数 string 是检索标签中的非属性字符串。

.children 是标签下行遍历的一种属性。标签一共有三种遍历形式,分别是下行遍历、上行遍历和平行遍历。

下行遍历的三个属性:

  • .children 是循环遍历儿子节点
  • .descendants 是循环遍历所有子孙节点
  • .contents 是将该标签中所有儿子节点存入列表

上行遍历有以下两个属性:

  • .parent 是访问该节点的父节点标签
  • .parents 是循环遍历所有先辈节点

平行遍历有以下四个属性:

  • .next_sibling 是返回下一个平行节点的标签
  • .previous_sibling 是返回上一个平行节点的标签
  • .next_siblings 是返回后面所有平行节点的标签
  • .previous_siblings 是返回前面所有平行节点的标签

现在我们已经获取了 tbody 标签中所有孩子标签了,由于返回的是一个迭代器,你可以使用 list(data) 以列表的形式输出看一看获取到的数据结果。我们这里直接使用 for 语句去遍历 tr 标签。

for tr in data:
	print(tr)
#返回所有tr标签

运行结果后,可以看到每一对 tr 标签都被遍历了,但是我们需要的td标签中的非属性字符串。这里使用 isinstance(tr, bs4.element.Tag) 去判断 tr 是否是 bs4 标签类型的元素。再用搜索文档树的另一种方法 find_all() 查询到所有td标签并保存到列表 tds 里。

import bs4
info = []
for tr in soup.find('tbody').children:
    if isinstance(tr, bs4.element.Tag):
        tds = tr.findall('td')
        info.append([tds[0].string, tds[1].string, tds[4].string])
print(info)
'''
[['1', '哈佛大学', '100.0'],
 ['2', '斯坦福大学', '75.1'],
 ['3', '剑桥大学', '72.3'],
 ['4', '麻省理工学院', '69.0'],
 ['5', '加州大学-伯克利', '67.9'],
 ['6', '普林斯顿大学', '60.0'],
 ['7', '牛津大学', '59.7'],
 ['8', '哥伦比亚大学', '59.1'],
 ['9', '加州理工学院', '58.6'],
 ['10', '芝加哥大学', '55.1'],
 ['11', '加州大学-洛杉矶', '50.8'],
 ['11', '耶鲁大学', '50.8'],
 ......]
'''

find_all() 它能够查询所有符合条件的元素,以列表的形式返回查询结果。它的完整参数形式与 find() 相同,这里就不在赘述了,若忘记,请回看以上内容。现在所有的 td 标签都保存在 tds 里面,我们用 tag.string 去取出标签中的非属性字符串。这是 Tag 标签的基本属性之一,称为 NavigableString

完整代码

import requests
import bs4 import BeautifulSoup
import bs4

r = requests.get("https://labfile.oss.aliyuncs.com/courses/2184/2019%E8%BD%AF%E7%A7%91%E4%B8%96%E7%95%8C%E5%A4%A7%E5%AD%A6%E5%AD%A6%E6%9C%AF%E6%8E%92%E5%90%8D.html")   
r.encoding = r.apparent_encoding        #更改编码
html = r.text           #获取文本信息
soup = BeautifulSoup(html, "html.parser")      #解析文本
data = soup.find("tbody").children             #找出tbody标签的所有子标签(返回一个迭代器)

info = []
for tr in soup.find('tbody').children:
    if isinstance(tr, bs4.element.Tag):    #isinstance判断某个对象是否是某个类型
        tds = tr.find_all('td')    #查询所有td标签,并以列表形式返回
        info.append([tds[0].string, tds[1].string, tds[4].string])   #取出标签中的非属性字符串
print(info)

三、实例

爬取蓝桥云课课程名称:

image-20210430090858625

import requests
import bs4
from bs4 import BeautifulSoup

try:
    url = "https://www.lanqiao.cn/courses/"
    r = requests.get(url)
    print(r.raise_for_status)    #返回响应状态码
    r.encoding = r.apparent_encoding   #将编码修改为utf-8
    demo = r.text    #获取返回的页面
    #print(demo)
except:
    print("未能获取页面内容")
    
soup = BeautifulSoup(demo, 'html.parser')  #对页面进行解析
div = soup.find('body').div        #获取页面body标签中的div标签
a = div.find_all('a','link block')   #获取class='link block'的a标签
href_list = []   #设置一个存放课程链接的列表
div_list = []    #设置一个存放含有课程名称的div标签
for i in a:
    href_list.append("https://www.lanqiao.cn"+i.get('href'))  #向列表中填充课程链接(https://...+i.get('href'))
    div_list.append(i.find('div', 'course-cover relative'))  #向列表中填充含有课程名的div标签
#print(href_list)
#print(div_list)

img_list = []   #用于存放img标签
names = []          #用于存放课程名
info_dict = {}     #用于存放课程名与链接的映射字典
for i in div_list:
    img_list.append(i.find('img'))
for i in img_list:
    names.append(i.get('alt'))
for i in range(0, len(names)):
    info_dict[names[i]] = href_list[i]
    
print(info_dict)

image-20210430100528944

学完两个爬虫实例了,感觉重点在于对返回页面的结构分析上,还有遍历和取数据的一个思路。以前都是零散的学,现在算是系统的学了一边,麻雀虽小五脏俱全,基本的思路算是掌握了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值