Beautiful Soup
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式。
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是 lxml 。
推荐使用lxml作为解析器,因为效率更高. 在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必须安装lxml或html5lib, 因为那些Python版本的标准库中内置的HTML解析方法不够稳定。
下表列出了主要的解析器,以及它们的优缺点:
| 解析器 | 使用方法 | 优势 | 劣势 |
|---|---|---|---|
| Python标准库 | BeautifulSoup(markup, "html.parser") |
|
|
| lxml HTML 解析器 | BeautifulSoup(markup, "lxml") |
|
|
| lxml XML 解析器 |
|
|
|
| html5lib | BeautifulSoup(markup, "html5lib") |
|
|
html_doc = """ <html> <head> <title>The Dormouse's story</title> </head> <body> <p class="title"> <b>The Dormouse's story</b> <span>eng</span> <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a> </p> <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 class="story">...</p> """
标签选择器
选择元素
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') soup.title#返回是一个tag对象 # <title>The Dormouse's story</title> print(soup.head) # <head> # <title>The Dormouse's story</title> # </head> print(soup.p) # <p class="title"> #<b>The Dormouse's story</b> #<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> #</p> print(soup.a) # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
获取标签名称
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.title.name) # title
获取标签属性
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.a['href']) # http://example.com/elsie print(soup.a.attrs['href']) # http://example.com/elsie
获取标签文本内容
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.title.string) # The Dormouse's story
如果tag中包含多个字符串 ,可以使用 .strings 来循环获取:
for string in soup.strings: print(repr(string)) # u"The Dormouse's story" # u'\n\n' # u"The Dormouse's story" # u'\n\n' # u'Once upon a time there were three little sisters; and their names were\n' # u'Elsie' # u',\n' # u'Lacie' # u' and\n' # u'Tillie' # u';\nand they lived at the bottom of a well.' # u'\n\n' # u'...' # u'\n'
#输出的字符串中可能包含了很多空格或空行,使用.stripped_strings可以去除多余空白内容
for string in soup.stripped_strings: print(repr(string))
嵌套选择
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.head.title.string)#返回是一个tag对象,可以在此之上继续选择 # The Dormouse's story
子节点
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.p.contents)#返回含有所有子节点tag对象的一个列表 #['\n', <b>The Dormouse's story</b>, '\n', <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, '\n'] from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.p.children)#返回含有所有子节点tag对象的一个列表迭代器 #<list_iterator object at 0x037F8FE8> for i, child in enumerate(soup.p.children): print(i,child) #0 #1 <b>The Dormouse's story</b> #2 #3 <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> #4
子孙节点
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.p.contents)#返回含有所有子孙节点tag对象的一个列表 #['\n', <b>The Dormouse's story</b>, '\n', <span>eng</span>, '\n', <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, '\n'] from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.p.descendants)#返回含有所有子节点tag对象的一个列表迭代器 #<generator object Tag.descendants at 0x0130B808> for i, child in enumerate(soup.p.descendants): print(i,child) #0 #1 <b>The Dormouse's story</b> #2 The Dormouse's story #3 #4 <span>eng</span> #5 eng #6 #7 <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> #8 Elsie #9
兄弟节点
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.a.next_sibling)#下一个兄弟节点tag对象 print(soup.a.next_siblings)#下面所有兄弟节点tag对象 print(list(enumerate(soup.a.next_siblings))) from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.a.previous_sibling)#上一个兄弟节点tag对象 print(soup.a.previous_siblings)#上面所有兄弟节点tag对象 print(list(enumerate(soup.a.previous_siblings)))
搜索文档树
用来查找到想要查找的文档内容,着重介绍2个: find() 和 find_all()
过滤器
字符串
soup.find_all('b')#查找与字符串完整匹配的内容 # [<b>The Dormouse's story</b>]
正则表达式
import re for tag in soup.find_all(re.compile("^b")):#通过正则表达式的 search() 来匹配内容 print(tag.name) # body # b
列表
soup.find_all(["a", "b"])#如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回 # [<b>The Dormouse's story</b>, # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
True
#True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点 for tag in soup.find_all(True): print(tag.name) # html # head # title # body # p # b # p # a # a # a # p
方法
#如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 ,
#如果这个方法返回 True 表示当前元素匹配并且被找到,
#如果不是则反回 False def has_class_but_no_id(tag): return tag.has_attr('class') and not tag.has_attr('id') soup.find_all(has_class_but_no_id) # [<p class="title"><b>The Dormouse's story</b></p>, # <p class="story">Once upon a time there were...</p>, # <p class="story">...</p>]
标准选择器
find_all( name , attrs , recursive , string , **kwargs )
name
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.find_all("a"))#返回所有a标签的tag对象的列表 #[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>] print(soup.find_all('a')[0]) #<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
attrs
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.find_all("a"))#返回所有a标签的ta print(soup.find_all(attrs = {'id':'link2'}))#定义一个字典参数来搜索包含特殊属性的ta print(soup.find_all(id = 'link2'))#id、class_可以简写,class要加_ # [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
string
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.find_all("a", string="Elsie"))#返回所有字符串与 string 参数值相符的tag # [<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>] soup.find_all(string=["Tillie", "Elsie", "Lacie"]) # 列表 # ['Elsie', 'Lacie', 'Tillie'] soup.find_all(string=re.compile("Dormouse")) #正则表达式 # ["The Dormouse's story", "The Dormouse's story"] #find( name , attrs , recursive , string , **kwargs )#返回第一个 #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()
CSS选择器
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.select("title"))#传入字符串参数,返回是列表 # [<title>The Dormouse's story</title>] print(soup.select("p:nth-of-type(3)")) # [<p class="story">...</p>]
通过tag标签逐层查找
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.select("p a")) #[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
找到某个tag标签下的直接子标签
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.select("p > a")) #[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
获取属性
rom bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') print(soup.select('a[href]')) #[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>] from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') for a in soup.select('a'): print(a['id']) print(a.attrs['id'])#另外一种写法 #link1 #link2 #link3
获取文本内容
from bs4 import BeautifulSoup soup = BeautifulSoup(html_doc,'lxml') for a in soup.select('a'): print(a.get_text()) #Elsie #Lacie #Tillie
BeautifulSoup官方文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/#id37

浙公网安备 33010602011771号