BeautifulSoup简单介绍
常规采用正则表达式提取网页信息很不方便,BeautifulSoup是个针对网页的解析库,支持多种解析器。使用BeautifulSoup可以不用编写正则表达式去获取网页上的信息
BeautifulSoup的基本使用
html = """
<html>
<head>
<title>The Dormouse's story</title>
</head>
<body>
<p class="story">
Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">
<span>Elsie</span>注意:在Ubuntu上,有的图片打不开,因为下载的图片原本应该是png的格式,但他直接改后缀成jpg了,在Windows上能看(不是我改的,而是网页提供的就是改过了的)
</a>
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a>
and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>
and they lived at the bottom of a well.
</p>
<p class="story">...</p>
</body>
</html>
"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html,'lxml')
print(soup.p)
print(soup.p.name)
print(soup.p['class'])
print(soup.title.string)
print(soup.html.head.title.string)
标签选择器
通过soup.标签名的形式来获取标签的内容,比如soup.title、soup.p
如果文档中包含多个相同的标签,则返回的结果是第一个出现的的标签内容
获取名字
注意:在Ubuntu上,有的图片打不开,因为下载的图片原本应该是png的格式,但他直接改后缀成jpg了,在Windows上能看(不是我改的,而是网页提供的就是改过了的)
通过soup.标签名.name的形式获取标签名字,比如soup.title.name,返回’title’
获取属性
通过soup.标签名.attrs[‘属性名’]或者soup.标签名[‘属性名’]来获取标签相应的属性
获取内容
通过soup.标签名.string来获取标签底下的内容,经测试,如果内容中包含其他标签,返回值是None
嵌套使用
直接举例吧,print(soup.html.head.title.string)
子节点、父节点和兄弟节点
- soup.标签名.children
- soup.标签名.parents
- soup.标签名.next_siblings 获取后面的兄弟节点
- soup.标签名.previous_siblings 获取前面的兄弟节点
- soup.标签名.next_sibling 获取下一个兄弟标签
- souo.标签名.previous_sinbling 获取上一个兄弟标签
find_all和find
fing_all和find的基本用法一致,通过传入标签名和属性字典来查找内容,区别在于find_all会以列表形式返回所有结果,find只会返回找到的第一个结果
html='''
<div class="panel">
<div class="panel-heading">
<h4>Hello</h4>
</div>
<div class="panel-body">
<ul class="small" id="list-1">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>
<ul class="list" id="list-2">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>
<ul class="list list-small" id="list-3">
<li class="element">Foo</li>
<li class="element">Bar</li>
</ul>
</div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
# print(soup.find_all('ul'))
# print(type(soup.find_all('ul')[0]))
print(soup.find_all('ul', attrs={"class": "small"}))
print(soup.find_all('ul', attrs={"class": "list"})) #经测试属性内容用空格分开的话,只取一部分也能出结果
print(soup.find_all('ul', attrs={"class": "list-small"})) #经测试属性内容用空格分开的话,只取一部分也能出结果
print(soup.find_all('ul', attrs={"class": "list list-small"}))
在测试时发现,如果属性中的内容用空格分开了,那么只要用其中一段就能查询出来,比如上面的两个ul,其中一个的class=“list list-small”,这时,用list或者list-small都能查询出来
在find和find_all返回的结果上能进一步调用find_all和find
for ul in soup.find_all('ul'):
print(ul.find_all('li'))
CSS选择器
html='''
<div class="panel">
<div class="panel-heading">
<h4>Hello</h4>
</div>
<div class="panel-body">
<ul class="small" id="list-1">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>
<ul class="list" id="list-2">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>
<ul class="list list-small" id="list-3">
<li class="element">Foo</li>
<li class="element">Bar</li>
</ul>
</div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.select('.panel .panel-heading'))
print(soup.select('ul li'))
print(soup.select('ul,li'))
print(soup.select('#list-2 .element'))
print(soup.select('[id="list-3"]'))
for li in soup.select('li'):
print(li.get_text())
print(li['class'])
print(li.attrs['iclass'])
==.==表示"class" ==#==表示"id" 纯字符串表示标签名
标签1==,==标签2 找到所有的标签1和标签2
标签1 标签2 找到标签1内部的所有的标签2
上面两条并不一定都是标签,也可以是class或者id,上面两条主要解释逗号和空格所代表的层级关系
[attr] 可以通过这种方法找到具有某个属性的所有标签
通过get_text可以获取文本内容
通过==.attrs[]或者直接[]==的形式获取属性