目录
BeautifulSoup库简介
我们在使用requests库获得一个网页的信息后,只能够得到对应的网页内容要想要从这些网页内容中获得有用的信息,便需要对网页信息进行解析
BeautifulSoup库是解析、遍历、维护‘标签树’的功能库
<p class="title"></p> <!-- 一个标签-->
BeutifulSoup的基本元素
基本元素 | 描述 | 对应属性 |
---|---|---|
Tag | 标签,最基本的信息组成单元,分别用<>和</>标明开头和结尾 | |
Name | 标签名,如p | <tag>.name |
Attributes | 标签的属性,字典形式组织 | <tag>.attrs |
NavigableString | 标签内非属性字符串,<>…</>中字符串 | <tag>.string |
Comment | 标签内字符串注释部分,一种特殊的Comment类型 |
下面我们使用一个html文档来解释bs库中的基本元素
<!DOCTYPE html>
<html lang="en">
<body>
<br/>
<div name="div2" style="text-align:center">
<image alt="div2-img2" src="http://www.baidu.com/img/bdligo.png" href="http://www.baidu.com"></image></br>
<a href="http://www.baidu.com">百度搜索</a>
</div>
</body>
</html>
标签(tag)和名称(name)
属性attrs
文本信息(string)和注释(comments)
BeautifulSoup支持的解析器
解析器 | 使用格式 | 需安装的库 |
---|---|---|
bs4的HTML解析器 | Beautifulsoup(mk,'html.parser') | bs4 |
lxml的HTML解析器 | Beautifulsoup(mk,'lxml') | lxml |
lxml的XML解析器 | Beautifulsoup(mk,'xml') | lxml |
html5lib的解析器 | Beautifulsoup(mk,'html5lib') | html5lib |
注:mk为makeup,可以是一段标签,也可以是一个打开的html文档
基于bs4库的html文本遍历方法
当我们想要的节点不好定位时,可以找到目标节点的附近节点,通过这些附近节点来找到目标节点,这就需要使用到遍历方法来获取附近节点
下行遍历
属性 | 类型 | 描述 |
---|---|---|
next_element | 字符串 | 返回下一个节点 |
contents | 包含子节点列表 | 将所有子节点存入一个列表并返回 |
.children | 生成器(包含子节点) | 将所有子节点(只包含直接子节点)存入一个迭代器并返回 |
.descendants | 生成器(包含子节点) | 包含所有子孙节点,用于循环遍历 |
下行遍历方法
下行遍历方法
soup.body.contents[n] # body子节点列表中,索引值为n的节点
for child in soup.body.children: # 遍历儿子节点
print(child)
for chile in soup.body.descendants: # 遍历子孙节点
print(child)
上行遍历
属性 | 类型 | 描述 |
---|---|---|
previous_elements | 字符串 | 返回上一个节点 |
parent | 字符串 | 返回节点的父亲节点 |
parents | 生成器对象 | 返回所有先辈节点 |
soup.a.parent # 返回标签a的parent节点
soup.parent # soup是一个特殊的节点,它的parent为空
soup.html.parent # html是最高的parent,它的parent是自己
for parent in soup.a.parents: # 输出a的所有parent节点
if parent is None:
print(parent)
else:
print(parent.name)
平行遍历
平行遍历发生在同一个父节点下的个节点之间
属性 | 类型 | 描述 |
---|---|---|
next_sibling | 字符串 | 返回下一个平行节点标签 |
previous_sibling | 字符串 | 返回上一个平行节点标签 |
next_siblings | 生成器 | 返回后续所有平行节点标签 |
previous_siblings | 生成器 | 返回前序所有平行节点标签 |
for sibling in soup.a.next_siblings:
print(sibling)
for sibling in soup.a.previous_siblings:
print(sibling)
基于bs4库的格式化和编码
prettify方法,用于把要解析的字符串以标准的缩进格式输出,并且自动更正
我们以下面的一段html代码为例
<ul><li>列表中的第一项</li><li>列表中的第二项</li></ul>
代码实现
from bs4 import BeautifulSoup
soup=BeautifulSoup('<ul><li>列表中的第一项</li><li>列表中的第二项</li></ul>','html.parser')
print(soup.prettify())
代码执行结果
<ul>
<li>
列表中的第一项
</li>
<li>
列表中的第二项
</li>
</ul>
基于bs4的html内容查找方法
常用方法–**find_all()**方法
<>.find_all(name=None,attrs={},recursive=True/False,string=None,**kwargs)
返回一个列表类型存储查找结果
参数 | 描述 | 表示形式 |
---|---|---|
name | 标签名称的检索字符串 | 一个(‘a’)、多个[‘a’,‘b’]或所有(True),(带入正则表达式re.complie()) |
attrs | 标签属性值的检索字符串,可标记属性检索 | 模糊查找(带入正则表达式re.complie()),也可以直接指定一个属性值进行过滤,如href=‘http://www.baidu.com’(class要写成class_) |
recursive | 是否针对子孙所有节点进行搜索,默认True | 如soup.find_all('a') ,若将该参数设为Flase,则返回空列表因为soup子节点下没有a标签 |
string | 对尖括号中的文本内容进行检索 | 若string='python' ,则结果返回返回'python' (带入正则表达式re.complie()) |
**kwargs | 其它形参 | 如limit=None,用于限制返回结果的数量 |
find_all()方法的扩展方法
方法 | 描述 | 类型 | 参数是否与find_all()相同 |
---|---|---|---|
find() | 搜索只返回一个结果 | 字符串 | 是 |
find_parents() | 在先辈节点中搜索 | 列表 | 是 |
find_parent() | 在先辈节点中搜索 | 字符串 | 是 |
find_next_siblings() | 后续平行节点搜索 | 列表 | 是 |
find_next_sibling() | 后续平行节点中返回一个结果 | 字符串 | 是 |
find_previous_siblings() | 前序平行节点中搜索 | 列表 | 是 |
find_previous_sibling() | 前序平行节点中搜索,返回一个结果 | 字符串 | 是 |
BeautfulSoup解析网页实践
案例1:爬取豆瓣top250电影排数据
import requests,bs4,re
url='https://movie.douban.com/top250'
headers={'user-agent':'Mozzlia/5.0'}
response=requests.get(url,headers=headers)
print(response.status_code) # 检测是否请求成功
soup=bs4.BeautifulSoup(response.text,'html.parser') # “煲一锅汤”
ol=soup.find('ol',attrs={'class':"grid_view"}) # 找到ol节点作为起始定位点
li_list = ol.find_all('li') # 找到列表的节点名称
movie_info=[]
for li in li_list:
# name = detail.find('span')
name = li.find('span', class_='title').get_text() # get_text()函数用于从html中提取文本
hot = str(li.find(text=re.compile('\d+人评价'))) # 使用re库进行模糊匹配
star=li.find('span',class_='rating_num').get_text()
quote=li.find('span',class_='inq').get_text()
# print(name,hot,star,quote)
movie_info.append((name,hot,star,quote)) # 将获得的信息进入列表进行存储
for movie in movie_info:
print(movie)
代码执行结果
案例2:爬取微博热搜榜单
import requests
from bs4 import BeautifulSoup
url='https://s.weibo.com/top/summary'
headers={'user-agent':'Mozzila/5.0'}
resp=requests.get(url,headers=headers)
soup=BeautifulSoup(resp.text,'html.parser') # “煲一锅汤”
thead=soup.find('table') # 找到table节点作为起始定位点
trs=thead.find_all('tr') # 找到列表的节点名称
for tr in trs:
topic=tr.find('a')
if tr.find('span')==None: # 如果没有热度就跳过此次循环
continue
else:
hot=tr.find('span').get_text()
print(topic.get_text(),hot)
代码执行结果