beautifulsoup就是一个非常强大的工具,爬虫利器。beautifulSoup “美味的汤,绿色的浓汤”
一个灵活又方便的网页解析库,处理高效,支持多种解析器。利用它就不用编写正则表达式也能方便的实现网页信息的抓取
bs4简单使用
- bs4是一个html的解析工具,根据html的特征和属性来查找节点
1 from bs4 import BeautifulSoup 2 3 fp = open("./test.html", "r", encoding="utf-8") 4 print(fp)
- 初始化一个BeautifulSoup对象
1 soup = BeautifulSoup(fp, 'lxml') 2 # 参数1,是一个HTML字符串 3 # 参数2,代表一个解析器,因为bs4本身没有解析器,可以借助于外界的解析器来解析 5 print(soup)
- 1、根据标签来查找对象
1 print(soup.title) 2 print(soup.a) # 如果标签有多个,只提取第一个
- 2、获取标签的属性
1 a = soup.a 2 print(a.get("href")) # 用get函数来获取 3 print(a["href"]) # 用键值方式获取 4 print(a.attrs)
- 3、获取内容
1 li = soup.li 2 print(li.string) # 通过string属性获取,可以获取当前标签的字符串内容(包括注释),但是如果当前内容中有子标签则获取为空 3 print(li.get_text()) # 通过get_text函数获取,获取出当前节点的字符串和后代节点中所有的字符串并且拼接在一起,但是如果有注释则忽略
- 4、获取后代节点
1 body = soup.body 2 3 # 1)获取直接子节点 4 children = body.children 5 print(children) # 打印结果:<list_iterator object at 0x0000026E8ED16080> 6 7 # 2)获取后代节点 8 des = body.descendants 9 print(des) # 打印结果:<generator object descendants at 0x00000203556CD048>
- 5、获取兄弟节点
1 soup.a.next_siblings 获取后面的兄弟节点 2 soup.a.previous_siblings 获取前面的兄弟节点 3 soup.a.next_sibling 获取下一个兄弟标签 4 souo.a.previous_sinbling 获取上一个兄弟标签
- 6、获取父亲节点
1 通过 soup.a.parent 可以获取父节点的信息 2 3 通过 list(enumerate(soup.a.parents)) 可以获取祖先节点, 4 5 这个方法返回的结果是一个列表,会分别将a标签的父节点的信息存放到列表中, 6 以及父节点的父节点也放到列表中,并且最后还会讲整个文档放到列表中, 7 所有列表的最后一个元素以及倒数第二个元素都是存的整个文档的信息
- 7、用函数来查找
1 # 1)find函数 2 print(soup.find("a")) 3 print(soup.find("li",class_='hehe')) 4 print(soup.find("li",id='hehe')) 5 6 # 2)find_all函数 7 print(soup.find_all("a")) 8 9 # 3) select函数,根据css选择器来选取节点,返回值是一个列表 10 print(soup.select(".heihei")) 11 print(soup.select("#hehe")) 12 print(soup.select("[href='http://mi.com']")) 13 print(soup.select("[name='ok']"))
- 基础选择器:id选择器,#id值。class选择器,.class值。标签选择器,标签名。通用选择器,*。属性选择器 [某属性='某值']
- 组合选择器:选择器1选择器2...选择器n (如果这些选择器中有标签要放在最前面)
- 派生选择器:后代选择器:选择器1 选择器2 ... 选择器n
- 子选择器: 选择器1 > 选择器2 > ... > 选择器n
解析器
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,如果我们不安装它,
则 Python 会使用 Python默认的解析器,lxml 解析器更加强大,速度更快,推荐安装。
推荐使用lxml作为解析器,因为效率更高. 在Python2.7.3之前的版本和Python3中3.2.2之前的版本,
必须安装lxml或html5lib, 因为那些Python版本的标准库中内置的HTML解析方法不够稳定
基本使用
标签选择器
print(soup.p) 通过 soup.标签名 可以获得这个标签的内容
获取名称
通过soup.title.name 可以获得该title标签的名称,即title
获取属性
print(soup.p.attrs['name'])
print(soup.p['name'])
上面两种方式都可以获取p标签的name属性值
获取内容
print(soup.p.string) 结果就可以获取第一个p标签的内容
嵌套选择
print(soup.head.title.string) 通过嵌套的方式获取
标准选择器
find_all
find_all(name,attrs,recursive,text,**kwargs). 可以根据标签名,属性,内容查找文档
find
find(name,attrs,recursive,text,**kwargs) find返回的匹配结果的第一个元素
其他
find_parents()返回所有祖先节点,find_parent()返回直接父节点。
find_next_siblings()返回后面所有兄弟节点,find_next_sibling()返回后面第一个兄弟节点。
find_previous_siblings()返回前面所有兄弟节点,find_previous_sibling()返回前面第一个兄弟节点。
find_all_next()返回节点后所有符合条件的节点, find_next()返回第一个符合条件的节点
find_all_previous()返回节点后所有符合条件的节点, find_previous()返回第一个符合条件的节点
参数
name的用法
1 html=''' 2 <div class="panel"> 3 <div class="panel-heading"> 4 <h4>Hello</h4> 5 </div> 6 <div class="panel-body"> 7 <ul class="list" id="list-1"> 8 <li class="element">Foo</li> 9 <li class="element">Bar</li> 10 <li class="element">Jay</li> 11 </ul> 12 <ul class="list list-small" id="list-2"> 13 <li class="element">Foo</li> 14 <li class="element">Bar</li> 15 </ul> 16 </div> 17 </div> 18 ''' 19 from bs4 import BeautifulSoup 20 soup = BeautifulSoup(html, 'lxml') 21 print(soup.find_all('ul')) 22 print(type(soup.find_all('ul')[0]))
结果返回的是一个列表的方式。同时我们是可以针对结果再次find_all,从而获取所有的li标签信息
1 for ul in soup.find_all('ul'): 2 print(ul.find_all('li'))
attrs
attrs可以传入字典的方式来查找标签,但是这里有个特殊的就是class,因为class在python中是特殊的字段,所以如果想要查找class相关的可以更改attrs={'class_':'element'}或者soup.find_all('',{"class":"element}),特殊的标签属性可以不写attrs,例如id
1 html=''' 2 <div class="panel"> 3 <div class="panel-heading"> 4 <h4>Hello</h4> 5 </div> 6 <div class="panel-body"> 7 <ul class="list" id="list-1" name="elements"> 8 <li class="element">Foo</li> 9 <li class="element">Bar</li> 10 <li class="element">Jay</li> 11 </ul> 12 <ul class="list list-small" id="list-2"> 13 <li class="element">Foo</li> 14 <li class="element">Bar</li> 15 </ul> 16 </div> 17 </div> 18 ''' 19 from bs4 import BeautifulSoup 20 soup = BeautifulSoup(html, 'lxml') 21 print(soup.find_all(attrs={'id': 'list-1'})) 22 print(soup.find_all(attrs={'name': 'elements'}))
text
结果返回的是查到的所有的text='Foo'的文本
1 html=''' 2 <div class="panel"> 3 <div class="panel-heading"> 4 <h4>Hello</h4> 5 </div> 6 <div class="panel-body"> 7 <ul class="list" id="list-1"> 8 <li class="element">Foo</li> 9 <li class="element">Bar</li> 10 <li class="element">Jay</li> 11 </ul> 12 <ul class="list list-small" id="list-2"> 13 <li class="element">Foo</li> 14 <li class="element">Bar</li> 15 </ul> 16 </div> 17 </div> 18 ''' 19 from bs4 import BeautifulSoup 20 soup = BeautifulSoup(html, 'lxml') 21 print(soup.find_all(text='Foo'))
CSS选择器
通过select()直接传入CSS选择器就可以完成选择,熟悉前端的人对CSS可能更加了解,其实用法也是一样的
.表示class #表示id
标签1,标签2 找到所有的标签1和标签2
标签1 标签2 找到标签1内部的所有的标签2
[attr] 可以通过这种方法找到具有某个属性的所有标签
[atrr=value] 例子[target=_blank]表示查找所有target=_blank的标签
1 html=''' 2 <div class="panel"> 3 <div class="panel-heading"> 4 <h4>Hello</h4> 5 </div> 6 <div class="panel-body"> 7 <ul class="list" id="list-1"> 8 <li class="element">Foo</li> 9 <li class="element">Bar</li> 10 <li class="element">Jay</li> 11 </ul> 12 <ul class="list list-small" id="list-2"> 13 <li class="element">Foo</li> 14 <li class="element">Bar</li> 15 </ul> 16 </div> 17 </div> 18 ''' 19 from bs4 import BeautifulSoup 20 soup = BeautifulSoup(html, 'lxml') 21 print(soup.select('.panel .panel-heading')) 22 print(soup.select('ul li')) 23 print(soup.select('#list-2 .element')) 24 print(type(soup.select('ul')[0]))
获取内容
通过get_text()就可以获取文本内容
1 html=''' 2 <div class="panel"> 3 <div class="panel-heading"> 4 <h4>Hello</h4> 5 </div> 6 <div class="panel-body"> 7 <ul class="list" id="list-1"> 8 <li class="element">Foo</li> 9 <li class="element">Bar</li> 10 <li class="element">Jay</li> 11 </ul> 12 <ul class="list list-small" id="list-2"> 13 <li class="element">Foo</li> 14 <li class="element">Bar</li> 15 </ul> 16 </div> 17 </div> 18 ''' 19 from bs4 import BeautifulSoup 20 soup = BeautifulSoup(html, 'lxml') 21 for li in soup.select('li'): 22 print(li.get_text())
获取属性
或取属性的时候可以通过[属性名]或者attrs[属性名]
1 html=''' 2 <div class="panel"> 3 <div class="panel-heading"> 4 <h4>Hello</h4> 5 </div> 6 <div class="panel-body"> 7 <ul class="list" id="list-1"> 8 <li class="element">Foo</li> 9 <li class="element">Bar</li> 10 <li class="element">Jay</li> 11 </ul> 12 <ul class="list list-small" id="list-2"> 13 <li class="element">Foo</li> 14 <li class="element">Bar</li> 15 </ul> 16 </div> 17 </div> 18 ''' 19 from bs4 import BeautifulSoup 20 soup = BeautifulSoup(html, 'lxml') 21 for ul in soup.select('ul'): 22 print(ul['id']) 23 print(ul.attrs['id'])