Beautiful Soup

Beautiful Soup

Beautiful Soup有多个解析器如下:

解析器使用方法优势劣势
Python标准库BeautifulSoup(markup, “html.parser”)Python的内置标准库
执行速度适中
文档容错能力强
Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差
lxml HTML 解析器BeautifulSoup(markup, “lxml”)速度快
文档容错能力强
需要安装C语言库
lxml XML 解析器BeautifulSoup(markup, [“lxml”, “xml”])BeautifulSoup(markup, “xml”)速度快
唯一支持XML的解析器
需要安装C语言库
html5libBeautifulSoup(markup, “html5lib”)最好的容错性
以浏览器的方式解析文档
生成HTML5格式的文档
速度慢
不依赖外部扩展

创建beautifulsoup对象

创建beautifulsoup对象,有两种方式,一个是导入字符串,一个是打开文件的方式。

soup = BeautifulSoup(html_str, 'lxml', from_encoding="utf-8") 
------------------------------- 
soup = BeautifulSoup(open('index.html')) 

字符串的方式要指定解析器,打开文件的方式会自动匹配使用最合适的解析器。

四大对象种类

  • Tag

tag是HTML中的一个个标签。

查找的是在所有内容中第一个符合条件的标签 
print(soup.title) 
# <title>The Dormouse's story</title> 
标签的属性 
print(soup.title.name) 
# title 
print(soup.p.attrs) 
# {'class': ['title'], 'name': 'dromouse'} 
获取属性值 
print(soup.p['class']) 
# ['title'] 
修改属性值 
soup.p[s'class'] = 'Myclass' 
  • NavigableString

NavigableString是标签内文本的类型。

print(soup.p.string) 
#The Dormouse's story 
print(type(soup.p.string)) 
#<class 'bs4.element.NavigableString'> 
  • BeautifulSoup

BeautifulSoup就是soup的类型。

print (type(soup.name)) 
#<type 'unicode'> 
print (soup.name)  
# [document] 
print (soup.attrs)  
#{} 空字典 
  • Comment

Comment对象是一个特殊类型的NavigableString对象, 输出的内容不包含注释符号。但不好好处理它会对文本处理造成麻烦。

print (soup.a) 
下面这条输出了注释里面的内容 
print (soup.a.string) 
print (type(soup.a.string)) 
# <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a> 
# Elsie  
# <class 'bs4.element.Comment'> 

所以打印内容是最好做一个判断是否是Comment类型

if isinstance(soup.a.string, bs4.element.Comment): 
    print(soup.a.string) 
    print(type(soup.a.string)) 

遍历文档树

  • 直接子节点
.contents和.children属性 
.contents返回一个子节点列表 
print soup.head.contents  
#[<title>The Dormouse's story</title>] 
.children返回一个子节点生成器 
print soup.head.children 
#<listiterator object at 0x7f71457f5710> 
for child in  soup.body.children: 
    print child 
# <p class="title" name="dromouse"><b>The Dormouse's story</b></p> 
# <p class="story">Once upon a time there were three little sisters; and their names were 
# <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, 
# <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and 
  • 所有子孙节点
.descendants返回一个子孙节点的生成器 
for child in soup.descendants: 
    print child 
# <html><head><title>The Dormouse's story</title></head> 
# <body> 
# <p class="title" name="dromouse"><b>The Dormouse's story</b></p> 
# <p class="story">Once upon a time there were three little sisters; and their names were 
# <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a> 
  • 节点内容
.string只能返回该tag的内容和该tag只包含一个子节点的内容,一旦包含多个子节点返回None 
head只包含一个title节点 
print soup.head.string 
# The Dormouse's story 
print soup.title.string 
# The Dormouse's story 
html包含多个子节点 
print soup.html.string 
# None 
  • 多个内容
.strings通过遍历获取多个内容 
.stripped_strings除去空格和空行的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' 
for string in soup.stripped_strings: 
    print(repr(string)) 
    # u"The Dormouse's story" 
    # u"The Dormouse's story" 
    # u'Once upon a time there were three little sisters; and their names were' 
    # u'Elsie' 
    # u',' 
    # u'Lacie' 
    # u'and' 
    # u'Tillie' 
    # u';\nand they lived at the bottom of a well.' 
    # u'...' 
  • 父节点
.parent返回节点的直接父节点,string的节点,生成器   
.parents返回节点的所有父辈节点,生成器 
p = soup.p 
print p.parent.name 
#body 
content = soup.head.title.string 
print content.parent.name 
#title 
content = soup.head.title.string 
for parent in  content.parents: 
    print parent.name 
# title 
# head 
# html 
# [document] 
  • 兄弟节点

与本节点相处同一级的节点

.next_sibling获取该节点的下一个兄弟节点, 如果节点不存在返回None 
.previous_sibling获取该节点的上一个兄弟节点,如果节点不存在返回None 
!!!注意:实际文档中的tag的 .next_sibling 和 .previous_sibling 属性通常是字符串或空白,因为空白或者换行也可以被视作一个节点,所以得到的结果可能是空白或者换行 
print soup.p.next_sibling 
#       实际该处为空白 
print soup.p.previous_sibling 
#None   没有前一个兄弟节点,返回 None 
print soup.p.next_sibling.next_sibling 
#<p class="story">Once upon a time there were three little sisters; and their names were 
#<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, 
#<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and 
#<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>; 
#and they lived at the bottom of a well.</p> 
#下一个节点的下一个兄弟节点是我们可以看到的节点 
  • 全部兄弟节点
.next_siblings返回该节点后的所有兄弟节点生成器 
.previous_siblings返回该节点前的所有兄弟节点生成器 
for sibling in soup.a.next_siblings: 
    print(repr(sibling)) 
    # u',\n' 
    # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> 
    # u' and\n' 
    # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a> 
    # u'; and they lived at the bottom of a well.' 
    # None 
  • 前后节点
.next_element .previous_element当前节点的前后节点,不分级别层次。 
print soup.head.next_element 
#<title>The Dormouse's story</title> 
  • 所有前后节点
.next_elements .previous_elements返回该节点前后所有节点的迭代器 
for element in last_a_tag.next_elements: 
    print(repr(element)) 
# u'Tillie' 
# u';\nand they lived at the bottom of a well.' 
# u'\n\n' 
# <p class="story">...</p> 
# u'...' 
# u'\n' 
# None 

搜索文档树

find_all(name, attrs, recursive, text, **kwargs) 
  • name参数可以查找所有tag名字为name的节点,name可以传入字符串,正则表达式,列表, True, 方法。
字符串: 
soup.find_all('b') 
# [<b>The Dormouse's story</b>]   返回一个列表 
正则表达式: 
import re 
for tag in soup.find_all(re.compile("^b")): 
    print(tag.name) 
# body 
# b 
列表: 
soup.find_all(["a", "b"]) 
# [<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>] Truefor tag in soup.find_all(True): 
    print(tag.name) 
# html 
# head 
# title 
# body 
# p 
# b 
# p 
# a 
# a 
传方法: 
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>] 
  • keyword参数用来匹配节点的属性
soup.find_all(id='link2') 
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>] 
soup.find_all(href=re.compile("elsie")) 
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>] 
soup.find_all(href=re.compile("elsie"), id='link1') 
# [<a class="sister" href="http://example.com/elsie" id="link1">three</a>] 
!!!class是系统关键字,使用class_代替 
soup.find_all("a", class_="sister") 
# [<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>] 
data_soup = BeautifulSoup('<div data-foo="value">foo!</div>') 
data_soup.find_all(data-foo="value") 
# SyntaxError: keyword can't be an expression 
!!!使用attrs参数定义一个字典参数来包含特殊属性data-foo 
data_soup.find_all(attrs={"data-foo": "value"}) 
# [<div data-foo="value">foo!</div>] 
  • text 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, text 参数接受 字符串 , 正则表达式 , 列表, True。
soup.find_all(text="Elsie") 
# [u'Elsie'] 
  
soup.find_all(text=["Tillie", "Elsie", "Lacie"]) 
# [u'Elsie', u'Lacie', u'Tillie'] 
  
soup.find_all(text=re.compile("Dormouse")) 
[u"The Dormouse's story", u"The Dormouse's story"] 
  • limit 参数限制返回结果的数量
soup.find_all("a", limit=2) 
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, 
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>] 
  • 如果只想搜索tag的直接子节点,可以使用参数 recursive=False
soup.html.find_all("title") 
# [<title>The Dormouse's story</title>] 
  
soup.html.find_all("title", recursive=False) 
# [] 

css选择器

  • 标签名查找
print soup.select('title')  
#[<title>The Dormouse's story</title>] 
  • 类名查找
print soup.select('.sister') 
#[<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>] 
  • id名查找
print soup.select('#link1') 
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>] 
  • 组合查找
print soup.select('p #link1') 
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>] 
print soup.select("head > title") 
#[<title>The Dormouse's story</title>] 
  • 属性查找
print soup.select('a[class="sister"]') 
#[<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>] 
  • 获取节点内的文字get_text()
alist = soup.select('a[class="sister"]') 
for a in alist: 
    print(a.get_text()) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值