
本文共 5208 字,大约阅读时间需要 17 分钟。
Beautiful Soup基础入门
- Requests 库
- 遍历文档树
- 搜索文档树
- 标签基本元素
- Beautiful Soup 库解析器
一、Beautiful Soup简介
就是一个可以从HTML或XML文件中提取数据的Python库。实例:在最好大学网爬取2021年软科类世界大学排名的数据。
二、基本步骤
用chrome浏览器去访问该网站,然后审查元素,定位相关信息对应的代码。整个实验的关键就在于如何遍历tbody标签的孩子标签,获取tr标签里的td标签的数据。
确定好之后,接下来使用requests.get()来获取整个页面的内容。用import requests来导入Requests库。
1、准备工作
import requestsr = 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) #检查状态码#200print(r.encoding) #检查编码方式#ISO-8859-1r.encoding = r.apparent_encoding #修改编码print(r.encoding)#utf-8
2、获取相应信息
r.text #获取整个页面内容
r.headers #获取页面头信息
html = r.textprint(html)#输出html代码header = r.headersprint(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 BeautifulSoupsoup = BeautifulSoup(html, "html.parser")print(soup)#返回有格式的html代码
4、遍历和搜索文档树
每个标签都有一个名字,每个标签可以有0个或者多个属性,标签之间的字符串是非属性字符串或者注释,如下图所示:
我们的实验任务是要获取页面上的三类数据,分别是学校排名、学校名字和学校总分。所以,我们需要遍历标签树,搜索到这三类数据并保存到列表中。从上面的内容我们已经知道,所需要的数据是在 tbody
的子标签里,所以我们需要使用 find()
去遍历 tbody
标签的孩子标签。
data = soup.find("tbody").childrenprint(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 bs4info = []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 requestsimport bs4 import BeautifulSoupimport bs4r = 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)
三、实例
爬取课程名称:
import requestsimport bs4from bs4 import BeautifulSouptry: 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)
学完两个爬虫实例了,感觉重点在于对返回页面的结构分析上,还有遍历和取数据的一个思路。以前都是零散的学,现在算是系统的学了一边,麻雀虽小五脏俱全,基本的思路算是掌握了。
发表评论
最新留言
关于作者
