一、beautiful soup 是Python的一个HTML或XML的解析库。
他提供一个简单的、Python式的函数来处理导航、搜索、修改分析数等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。
beautiful soup 自动将输入文档转化为Unicode编码,输出文档转化为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时你仅仅需要说明一下原始的编码方式就可以了。
from bs4 import BeautifulSoup soup=BeautifulSoup('<p>hello</p>','lxml')
print(soup.p.string)
# 返回了p标签的内容
html=‘<html>
<head><title>story</title></head>
<body><div>
<p class='t1' name='t2'>我的天,蒙蔽了</p>
</div></body>'
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
print(soup.prettiful()) #例子的html节点没有闭合 缺少标签</html> 返回的完整html不是prettiful做的是初始化BeautifulSoup时就完成了
print(soup.title.string) #返回标题的内容
print(soup.title) #返回的是<title>story</title>
print(soup.head) #<head><title>story</title></head>
prinp(soup.p) #<p>我的天,蒙蔽了</p>
#当有多个属性时,此种方法只能获取第一个匹配的节点
二、提取信息
上面演示了调用string属性来获取文本的值,那么如何获得节点属性的值?
(1)可以利用name属性获取几点的名称,这里还是以上面文本为例,选取title节点然后调用name属性就可以获得节点名称
print(soup.title.name) #title 不懂为什么出这个命令 我可能看不出来吧
(2)获取属性
每个节点都可能有多个属性,比如id和class等,选择这个节点后,可以调用class获取所有属性
print(soup.p.attrs)
print(soup.p.attrs['name']
运行结果如下:
{'class':['t1'],'name':'t2'}
['t2']
另
print(soup.p['class']
print(soup.p['name']
获取需要的属性
(3)获取内容
可以利用string获取内容
print(soup.p.string)
三、
(1)嵌套选择
上面的语句中返回的都是bs4.element.Tag类型。
所谓嵌套的意思是通过第一个,可以一直找到此节点下的最后一个属性。
ex:
print(soup.head.title.string)
(2)关联选择
在做选择时,有时候不能做到一步就选到想要的节点元素。需要以他为基点,再选择它的子节点、父节点、兄弟节点等。
子节点和子孙节点
html=''
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
print(soup.p.contents) #打印的是p节点下的所有节点与内容 包括 的一个列表
还可以用children属性得到相应的结果
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
print(soup.p.children) 得到的是一个生成器所以要想得到结果怎么办呢?<list_iterator object at 0x00000000029C8E80>
for i,child in enumerate(soup.p.children):
print(i,child)
用descendants 得到p节点下的所有属性 包括吧节点<a>aaaa</a>中的内容单独提出来
得到的也是一个生成器需要 去想办法得到其需要的东西
父节点和祖先节点
print(soup.a.parent)
获取选择的a节点的第一个父节点 直接其节点的代码
print(soup.a.parents)
获得的是a节点外的所有祖先节点 返回的是一个生成器
兄弟节点
print(soup.a.next_sibling) 获取节点的下一个兄弟元素
print(soup.a.previous_sibling) 获取节点的上一个兄弟元素
print(list(enumerate(soup.a.next_siblings))) 获取所有的a节点以后的所有兄弟节点
print(list(enumerate(soup.a.previous_siblings))) 获取所有的a节点以前所有的兄弟节点
方法选择器
find_all() 就是查找所有符合属性的元素,给他传入一些条件就传出,所有符合跳进的元素
它返回的是一个列表,
print(soup.find_all(name='ul')
还可以进行嵌套查询,例如查询里面的li节点
for ul in soup.find_all(name='ul'):
print(ul.find_all(name='li'))
for li in ul.find_all(name='li;)
print(li.string)
返回了li的所有文本内容
attrs()
除了根据节点名查询,
print(soup.find_all(attrs={'id':'name1'}))
print(soup.find_all(attrs={'name':'elements'}))
这里查询的时候传入的是attrs参数,参数的类型是字典类型,,得到结果是列表形式,包含的内容就是符合条件的节点。
对于一些常用的属性,比如id class 等 我们可以不用attrs来传递。
ex:
from bs4 import BeautifulSoup
soup=Beautiful(html,'lxml')
print(soup.find_all(id='index'))
print(soup.find_all(class_='element'))
注意:由于class是Python的关键字,所以在这里的class用class_ 来代替
返回的结果依然是列表
text 参数可以用来匹配节点的文本,传入的形式可以是字符串,可以使正则表达式对象。
返回的是文本,不包括节点。
find()
除了find_all()外还有find()方法,只不过后者返回的是单个元素,也就是第一个匹配的元素,而前者返回的是所有匹配的元素组成的列表。
还有很多查询方法:
find_parents()find_parent() 返回所有符合条件的祖先节点/一个
find_next_siblings() find_next_sibling() 后面的兄弟节点
find_previous_siblings() find_previous_siblings() 前面的兄弟节点
find_all_next() find_next() 返回所有后面符合条件的节点 一个
find_all_previous find_previous() 返回所有前面符合条件的节点 一个
CSS选择器
熟悉web开发的肯定熟悉选择器,不熟悉,请自行学习。
使用选择器时,调用select(),传入相应的css选择器即可。
ex:
print(soup.select('.first .second)) 类选择器
print(soup.select('div ul') 标签选择器
print(soup.select('#id .first)) id选择器 加类选择器
输出的都是列表
嵌套选择:
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
for ul in soup.select('ul'):
print(ul.select('li')) 获ul中的li节点
print(ul['id]) 获取属性
print(ul.attrs['id']) 获取属性
获取文本
print(soup.select('li').get_text())
print(soup.select('li').string()) 它俩的效果一致
总结:
推荐使用lxml,必要时使用lxml.parser
节点选择筛选功能弱,但速度块
建议使用find() find_all()查询单个或者多个结果
css选择器也是个不错的选择