文章目录
三、BeautifulSoup库的基本元素(bs4.element)
上面所述的方法返回的结果都是列表的形式,如果想要遍历这个列表,可以使用get_text()方法来获取节点的内容
引言😜
在学习BeautifulSoup库之前,想先和大家简单介绍一下这个库它到底能干啥,开玩笑来说“我时间很宝贵的,你什么身份,我什么地位,你有什么值得我学习的呢?”,那么下面是我向大家所罗列BeautifulSoup库的一些功能,也是我们接下来学习的主要内容:
-
解析html流程说明
-
识别标签
-
提取内容
-
查看标签信息
-
其他提取细节
废话不多说,这节课就让我来和大家一起稍微全面学习一下bs4这个库,研究一下它的作用,然后再搭配一些实例操作加深大家对它的理解,当然也不会完全脱离课本内容,希望能对大家有所帮助!
bs4库入门讲解
一、Beautifulsoup库的安装
在cmd中:
pip install beautifulsoup4
在操作过程中用到的URL:http://python123.io/ws/demo.html
二、对Beautifulsoup库浅浅试用一下
先导入一下url,查看网页内容(jupyter Notebook)
import requests
r = requests.get("http://python123.io/ws/demo.html")
#r.status_code
#r.encoding = r,apparent_encoding
r.text
#使用demo变量存储一下相关内容
demo = r.text #在后续讲解过程中会经常使用这个变量
导入bs4:
from bs4 import BeautifulSoup
将demo页面进行优化(也称“熬汤”)
soup = BeautifulSoup(demo, "html.parser") #"html.parser"指的是解析页面的方式,由于demo使得内容是html的形式,故使用html的方式解析
#而书中soup = BeautifulSoup(html, "lxml")采用的是lxml解析器
#关于解释器相关应用后期在做详细解释
print(soup.prettify()) #prettify()方法是将demo内容优化为标准格式,可以使得内容更清晰
总结:如何使用BeautifulSoup库,简单来说就两步
(1)调用bs4引入 (2)soup = BeautifulSoup('<p>data</p>', 'html.parser')
BeatifulSoup的基础
一、BeautifulSoup的“李姐”
我们知道任何一个html文件我们打开它的源代码可以知道他是一组尖括号构成的标签组织起来的,每一对尖括号组成一个标签,而各种标签之间又存在上下级关系,最终相互组合形成了一个标签树
<html>
<head>
<title>我真帅</title>
</head>
<body>
<p>
<a>...</a>
</p>
</body>
</html>
可以说BeautifulSoup库是一个能够解析、遍历、维护“标签树”的功能库,只要你提供的文件是标签类型,那么BeautifulSoup库都能对其进行一个很好的解析
虽然不同的标签功能不同,但它们中所包含的属性大体类似,下面以<p>标签为例:
<p class="title"> ...</p>
Name Attribute
成对出现 0个或多个,一般是以键值对构成
问题1:如何理解BeautifulSoup库这个类呢?😉
BeautifulSoup库本身解析的是html和xml的文档,而这个文档是与前面所提到的标签树是一一对应的,那么经过了BeautifulSoup类的处理后,可以使得每一个标签树转换成BeautifulSoup类,而在实际处理过程中我们时常将html文档、标签树以及BeautifulSoup看成是等价的,在此基础上我们就可以通过BeautifulSoup类使得这个标签树成为一个变量如soup = BeautifulSoup(demo, "html.parser")
,对该变量的处理,也即是对标签树处理
简单来说:BeautifulSoup对应一个HTML和XML文档的全部内容
二、BeautifulSoup库的其他解析器
解析器 | 使用方法 | 条件 |
---|---|---|
bs4的HTML解析器 | BeautifulSoup(mk, ‘html.parser’) | 安装bs4 |
lxml的HTML解析器 | BeautifulSoup(mk, ‘lxml’) | pip install lxml |
lxml的XML解析器 | BeautifulSoup(mk, ‘xml’) | pip install lxml |
html5lib的解析器 | BeautifulSoup(mk, ‘html5lib’) | pip install html5lib |
有关各种解析器的详细解释在这就不多做说明了,大家可以参考书中第79页,我在这里讲解的相关操作是基于第一种解析器,但每种解析器中的基本元素的使用方法都比较类似,如果想要更加快速有效的解析文档内容,可以尝试使用其他的解析器
三、BeautifulSoup库的基本元素(bs4.element)
基本元素 | 说明 | |
---|---|---|
Tag | 标签,最基本的信息组织单元 | |
Name | 标签名,获取标签名格式:<tag>.name | |
Attributes | 标签属性,字典形式组织,格式:<tag>.attrs | |
NavigableString | 标签内非属性字符串,<>…</>中字符串,格式:<tag>.string | |
Comment | 标签内字符串的注释部分,一种特殊的Comment类型 |
四、使用demo变量来分析html页面
from bs4 import BeautifulSoup
soup = BeautifulSoup(demo, "html.parser")
soup.title #看一下页面的title
tag = soup.a #定义一个标签,注意当HTML中存在多个<a>标签时,读取第一个标签内容
tag #查看标签内容
#获取标签名字的方法
soup.a.name
soup.a.parent.name #<a>标签父标签名,也即上一级标签
soup.a.parent.parent.name #“上上签”
#获取标签属性方法,查看结果可知这是一个字典类型,既可以通过字典的形式进行索引
tag.attrs
tag.attrs["class"]
#查看标签属性的类型
type(tag.attrs)
type(tag)
#下面让我们看一下NavigableString元素,表示的是尖括号之间的那一部分字符串,比如
soup.a.string
soup.p.string
type(soup.p.string)
做一个小总结
BeautifulSoup有五种基本元素,分别是标签(Tag),标签名(Name),标签的属性(Attribute),标签内非属性字符串(NavigableString)以及标签内的注释部分(Comment)。理解好BeautifulSoup库的五种基本元素是使用BeautifulSoup的基础。
然后就是html页面中标签的解析
回归课本学习find()&find_all()使用方法
介绍🍨
(1)find()方法:用于查找符合查询条件的标签节点 (2)find_all() 方法:查找所有符合查询条件的标签节点,并返回一个列表
这两个方法用到的参数是一样的,如下所示:
find(self, name=None, attrs={}, recuresive=True, text=None, limit=None, **kwargs)
find_all(self, name=None, attrs={}, recuresive=True, text=None, limit=None, **kwargs)
1. name参数
(1)传入字符串查找:在搜索的过程中传入一个字符串,BeautifulSoup对象会查找与字符串完全匹配的内容
soup.find_all('a')
(2)传入正则表达式:如果传入一个正则表达式,那么BeautifulSoup对象会通re模块中的match()函数进行匹配
import re
for tag in soup.find_all(re.compile("^b")):
print(tag.name)
(3)传入列表:当我们想要查找的标签不在单一一种时,我们也可以使用列表的方式传入参数,查找我们所需的标签
soup.find_all(['a', 'b'])
2. attrs参数
如果指定名字的参数不是搜索方法中内置参数名,那么在进行搜索时,会把该参数当做指定名称的标签中的属性来搜索
soup.find_all(id='link2')
若传入多个指定名字的参数,则可以同时过滤出标签中的多个属性,书中采用的是正则表达式的方法,这里就不做过多解释了
注意点 💥:
-
如果使用的标签名称是class,由于class属于Python中的关键字,所以需要在class的后面加一个下划线,如:
soup.find_all('a', class_='title')
-
有些标签的属性名称是不能直接使用的,例如HTML5中的“data-”属性,在程序中使用会出现SyntaxError异常信息,可以使用传入字典来搜素
find_all(attrs={"data-...":""})
3. text参数
指定搜索文档中字符串的内容,传什么搜什么
方式:
soup.find_all(text='...')
4. limit参数
当使用find_all()索引非常大的标签树时,那么便利查找的速度是比较慢的,如果不需要全部的结果,此时我们可以通过限制结果的数目来减少索引的所需的时间,也即limit限制数
soup.find_all('a', limit=2)
5. recursive参数
在使用find_all()方法时,BeautifulSoup对象会检索当前节点的所有子节点(也包括自己),而如果只想搜索当前节点的直接子节点,就可以使用recursive=False
soup.html.find_all('title', recursive=False)
通过CSS选择器进行搜索
关于CSS是什么,大家都学过,这里就不做介绍了哈😸
这里所用到的方法是select()方法
1. 通过标签查找
在编写CSS时,标签的名称不用加任何修饰
直接传入标签名即可
soup.html.find_all('title', recursive=False)
2. 通过类名查找
在编写CSS时,需要在雷鸣前面加上“.”
soup.select('.className')
3. 通过id名查找
在编写CSS时,需要在id名称前面加上“#”
soup.select('#id')
4. 通过组合的形式查找
多个参数协同搜索,例如锁定p标签中满要求的id值,但中间需加空格
soup.select('p #id')
5. 通过属性查找
可以通过属性元素查找,属性需要用中括号括起来,但这里属性与标签之间不能存在空格
soup.select('a[href="url"]')
同样也可以使用组合的形式
soup.select('p a[href="url"]')
上面所述的方法返回的结果都是列表的形式,如果想要遍历这个列表,可以使用get_text()方法来获取节点的内容
爬取招商银行商品信息实例运用
import csv
import pandas as pd
import requests
from bs4 import BeautifulSoup
#检测网页时都访问异常,正常则返回网页相关信息
def htmlText(url):
try:
r = requests.get(url) #get请求
r.raise_for_status() #检测连接状态,若状态码不是200,则抛出异常信息
r.encoding = r.apparent_encoding
return r.text
except:
return "访问异常!"
url = "https://www.51credit.com/jifen/zhaoshang/p1/"
demo = htmlText(url)
bf = BeautifulSoup(demo, 'lxml') #解析网页内容,并存储在生成的BeautifulSoup对象中
#通过开发者工具查看,定位索要爬取的位置在<ul class="list_pro clearfix">中
ul_data = bf.find_all('ul', class_="list_pro clearfix")
#通过由浅入深可知查找可知,我们所需爬取的数据分别位于<p>和<h4>两个标签之中
#通过属性和标签名来进行索引
commodity_data = []
#下面再通过循环遍历打印出整个<ul class="list_pro clearfix">内容
for i in ul_data[0].find_all('li'): #ul_data[0],将其转化为列表的形式迭代
p_data = i.find_all('p', class_='c6')
h4_data = i.find_all('h4')
for h4 in h4_data[0].find_all('a'): #获取title值,即商品名称
goods = h4['title']
for p1 in p_data[0].find_all('a')[0]: #返回一个列表,并取第一个值
bank = p1.strip()
for p2 in p_data[0].find_all('a')[1]: #同上
prd_types = p2.string
commodity_data.append([goods]+[prd_types]+[bank])#将商品和类型还有银行组合成一个数组,与csv文件中的列相对应
title = ["商品名称", "商品类别", "银行"]
with open('C:/Users/123/Desktop/commodity-data.csv', 'a+', newline='', encoding='utf-8') as f:
w = csv.writer(f)
w.writerow(title)
for row in commodity_data:
w.writerow(row)
r = pd.read_csv('C:/Users/123/Desktop/commodity-data.csv')
r
爬取结果