BeautifiulSoup和lxml一样也是一个HTML/XML的解析器,主要功能是解析和提取HTML/XML数据。
lxml只会局部遍历,而BEautifulSoup是基于HTML DOM(Document OBject Model)的,会载入整个文档,解析整个DOM树,因此,时间和内存开销都会大很多,所以性能低于lxml。
BeautifulSoup用来解析HTML比较简单,API非常人性化,支持CSS选择器、python标准库中的HTML解析器,也支持lxml的XML解析器。
几大解析工具对比:
解析工具 | 解析速度 | 使用难度 |
BeautifulSoup | 最慢 | 最简单 |
lxml | 快 | 简单 |
正则 | 最快 | 最难 |
安装和和文档:
1. 安装:pip install bs4
2. 中文文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html
常见的四种对象:
1. Tag:BeautifulSoup中所有的标签都是Tag类型,并且BeautifulSoup的对象本质上也是一个Tag类型。所以一些方法比如:find、find_all并不是BeautifulSoup的,而是Tag的。
2. NavigableStrings: 继承自python中的str,用起来就跟使用python的str一样。
3. BeautifulSoup: 继承自Tag。用来生成BeautifulSoup树。对于一些查找方法:比如:find、select,其实还是Tag的。
4. Comment:继承自NavigableStrings。
beautifulSoup 的基本使用:
# pip install lxml bs = BeautifulSoup(html,'lxml') print(bs.prettify())
"lxml"是解析器,使用之前先安装;html 为符合HTML格式的字符串;‘prettify()’函数是为了规范解析出来的内容,合理、美观。
find_all的使用:
1.在提取标签的时候,第一个参数是标签名字。如果在提取标签的时候想要使用标签属性进行过滤,那么可以在这个方法中通过关键字参数的形式,将属性的名字以及对应的值传进去(如果与python的关键字重复,则加下划线,如:class_),或者使用‘attrs'属性,将所有的属性以及对应的值放在一个字典中传给'attrs'属性。
2. 可以使用'limit'参数,限制提取标签的数量。
from bs4 import BeautifulSoup soup = BeautifulSoup(html,'lxml') # 1. 获取所有的tr标签 trs = soup.find_all('tr') for tr in trs: print(tr) # 2.获取第二个tr标签 tr = soup.find_all('tr',limit=2)[1] print(tr) # 3. 获取所有class等于even的tr标签 # 方式一: trs = soup.find_all('tr',class_='even') # 方式二: trs = soup.find_all('tr',attrs={'class':'even'}) for tr in trs: print(tr) # 4. 将所有id等于test,class也等于test的a标签提取出来。 aList = soup.find_all('tr',id='test',class_='test') aList = soup.find_all('tr',attrs={'id':'test','class':'test'}) for a in aList: print(a) # 5. 获取所有a标签的href属性 aList = soup.find_all('tr') for a in aList: # 方式一 href = a['href'] # 方式二 href = a.attrs['href'] print(href) # 6,获取所有职位信息(纯文本) movies = [] trs = soup.find_all('tr')[1:] for tr in trs: movie = {} # 方法一 tds = tr.find_all('td') title = tds[0].string category = tds[1].string nums = tds[2].string city = tds[3].string pubtime = tds[4].string movie = { 'title':title, 'category': category, 'nums':nums, 'city':city, 'pubtime':pubtime } movies.append(movie) # 方法二 infos = list(tr.stripped_strings) movie = { 'title': infos[0], 'category': infos[1], 'nums': infos[2], 'city': infos[3], 'pubtime': infos[4] } movies.append(movie)
find 与 find_all的区别:
1. find:只查找一个元素标签就返回;
2.find_all:将所有满足条件的标签以列表形式全部返回,
string、strings、stripped_strings和get_text 方法的区别:
1. string:获取某个标签下的非标签字符串,返回的是一个字符串,只能获取一行数据,如果有多个换行符时,就无法获取有用数据;
2. strings: 获取某个标签下的子孙非标签字符串,返回的是一个生成器;
3. stripped_strings:获取某个标签的子孙非标签字符串,会去掉空白字符,返回的是一个生成器;
4. get_text: 获取某个标签下的子孙非标签字符串,以普通字符串返回。
select方法:
有时候使用css选择器可以更加的方便。使用css选择器应该使用select方法:
(1)通过标签名查找:
soup.select('a')
(2) 通过类名查找
通过类名查找,应该在类的前面加一个 . 。比如要查找class=sister的标签:
soup.select('.sister')
(3)通过id查找
通过id 查找,应该在id的名字前面加一个#号。比如要查找id = link1的标签:
soup.select('#link1')
(4)组合查找
例如要查找p标签中,id等于link1的内容,二者需要空格隔开。
soup.select('p #link1'
直接子标签查找,则使用>分隔:
soup.select('head>title')
(5)通过属性查找
通过属性查找时,属性应该使用中括号括起来,属性和标签属于同一节点,中间不能加空格,否则无法匹配到。
soup.select("a[href='http://www.example.com']")
from bs4 import BeautifulSoup soup = BeautifulSoup(html,'lxml') # 1. 获取所有的tr标签 trs = soup.select('tr') for tr in trs: print(tr) # 2.获取第二个tr标签 tr = soup.select('tr')[1] print(tr) # 3. 获取所有class等于even的tr标签 # 方式一: trs = soup.select('.even') # 方式二: trs = soup.select("tr{"class':'even'}") for tr in trs: print(tr) # 4. 获取所有a标签的href属性 aList = soup.select('a') for a in aList: href = a['href'] # 5,获取所有职位信息(纯文本) trs = soup.select('tr') for tr in trs: infos = list(tr.stripped_strings) print(infos)
contents 和 children:
返回某个标签下的直接子元素,其中包括字符串。区别是:contents返回的是一个列表,children返回的是一个迭代器。