1、Beautiful Soup简介
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库。Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。不需要考虑编码方式,除非文档没有指定一个编码方式,这种情况Beautiful Soup就不能自动识别编码方式。Beautiful Soup已成为和lxml、html6lib一样出色的python解释器,为用户灵活地提供不同的解析策略或更高的效率。
英文文档:
中文文档:
2、Beautiful Soup解析器
Beautiful Soup支持Python标准库中的HTML解析器,也支持一些第三方的解析器,如下表,
解析器  | 代码  | 优点  | 缺点  | 
bs4的HTML 解析器  | BeautifulSoup(markup, "html.parser")  | 1)Python的内置标准库 2)执行速度适中 3)文档容错能力强  | 部分版本中文档容错能力差  | 
lxml HTML 解析器  | BeautifulSoup(markup, "lxml")  | 1)速度快 2)文档容错能力强  | 需要安装C语言库  | 
lxml XML 解析器  | BeautifulSoup(markup, ["lxml-xml"]) BeautifulSoup(markup, "xml")  | 1)速度快 2)唯一支持XML的解析器  | 需要安装C语言库  | 
html5lib 解析器  | BeautifulSoup(markup, "html5lib")  | 1)最好的容错性 2)以浏览器的方式解析文档 3)生成HTML5格式的文档  | 1)速度慢 2)不依赖外部扩展  | 
注意:如对性能效率要求高,可以使用lxml HTML 解析器。
3、获取元素标签的方法
基本元素  | 说明  | 
Tag  | 标签,最基本的信息组织单元,分别用<>和标明开头和结尾  | 
Name  | 标签的名字,< p >…< /p >的名字是'p',格式: .name  | 
Attributes  | 标签的属性,字典形式组织,格式: .attrs  | 
NavigableString  | 标签内非属性字符串,<>…中字符串,格式: .string  | 
Comment  | 标签内字符串的注释部分,一种特殊的Comment类型  | 
1)使用CSS选择器的语法
使用CSS选择器的语法查找标签元素,可以使用select()方法,代码如下,
import bs4
import requests
response = requests.get("https://en.wikipedia.org/wiki/Mathematics")
if response is not None:
    html = bs4.BeautifulSoup(response.text, 'html.parser')
    title = html.select("#firstHeading")[0].text
    paragraphs = html.select("p")
    for para in paragraphs:
        print (para.text)
    intro = '\n'.join([ para.text for para in paragraphs[0:5]])
    print (intro)
2)使用find_all()和find()方法
find()返回找到的第一个标签,find_all()以list的形式返回找到的所有标签。select()使用CSS选择器的语法更方便,find_all使用更广,可调的参数也更多。
from bs4 import BeautifulSoup  
  
html = '''
<html><head><title>cjavapy</title></head>  
<body>  
<p class="title" name="dromouse"><b>cjavapy</b></p>  
<p class="story">www.cjavapy.com 
<a href="http://example.com/lacie" class="sister" id="link2">pandas</a> and  
<a href="http://example.com/tillie" class="sister" id="link3">python</a>;  
cjavapy</p>  
</body>  
</html>  
'''
  
soup = BeautifulSoup(html, "lxml")  
body_tag = soup.find(name='body')  
print body_tag
tags = soup.find_all(name='p')  
for tag in tags:  
    print tag4、元素的遍历
1)父级遍历
属性  | 说明  | 
.parent  | 节点的父亲标签  | 
.parents  | 节点先辈标签的迭代类型,用于循环遍历先辈节点  | 
示例代码:
from bs4 import BeautifulSoup  
  
html = '''
<html><head><title>cjavapy</title></head>  
<body>  
<p class="title" name="dromouse"><b>cjavapy</b></p>  
<p class="story">www.cjavapy.com 
<a href="http://example.com/lacie" class="sister" id="link2">pandas</a> and  
<a href="http://example.com/tillie" class="sister" id="link3">python</a>;  
cjavapy</p>  
</body>  
</html>  
'''
  
soup = BeautifulSoup(html, "lxml")  
for child in soup.body.contents:
    print(child)
for child in soup.body.children:
    print(child)
for child in soup.body.descendants:
    print(child)
2)同级遍历
属性  | 说明  | 
.next_sibling  | 返回按照HTML文本顺序的下一个平行节点标签  | 
.previous_sibling  | 返回按照HTML文本顺序的上一个平行节点标签  | 
.next_siblings  | 迭代类型,返回按照HTML文本顺序的后续所有平行节点标签  | 
.previous_siblings  | 迭代类型,返回按照HTML文本顺序的前续所有平行节点标签  | 
示例代码:
from bs4 import BeautifulSoup  
  
html = '''
<html><head><title>cjavapy</title></head>  
<body>  
<p class="title" name="dromouse"><b>cjavapy</b></p>  
<p class="story">www.cjavapy.com 
<a href="http://example.com/lacie" class="sister" id="link2">pandas</a> and  
<a href="http://example.com/tillie" class="sister" id="link3">python</a>;  
cjavapy</p>  
</body>  
</html>  
'''
  
soup = BeautifulSoup(html, "lxml")  
for parent in soup.a.parents:
    if parent is None:
        print(parent)
    else:
        print(parent.name)
3)子级遍历
属性  | 说明  | 
.contents  | 子节点的列表,将 所有儿子节点存入列表  | 
.children  | 子节点的迭代类型,与.contents类似,用于循环遍历儿子节点  | 
.descendants  | 子孙节点的迭代类型,包含所有子孙节点,用于循环遍历  | 
示例代码:
from bs4 import BeautifulSoup  
  
html = '''
<html><head><title>cjavapy</title></head>  
<body>  
<p class="title" name="dromouse"><b>cjavapy</b></p>  
<p class="story">www.cjavapy.com 
<a href="http://example.com/lacie" class="sister" id="link2">pandas</a> and  
<a href="http://example.com/tillie" class="sister" id="link3">python</a>;  
cjavapy</p>  
</body>  
</html>  
'''
  
soup = BeautifulSoup(html, "lxml")  
for sibling in soup.a.next_sibling:
    print(sibling)
for sibling in soup.a.previous_sibling:
    print(sibling)
find()的扩展方法:
方法  | 说明  | 
<>.find()  | 搜索且只返回一个结果,同  | 
<>.find_parents()  | 在先辈节点中搜索,返回列表类型,同  | 
<>.find_parent()  | 在先辈节点中返回一个结果,同  | 
<>.find_next_siblings()  | 在后续平行节点中搜索,返回列表类型,同  | 
<>.find_next_sibling()  | 在后续平行节点中返回一个结果,同  | 
<>.find_previous_siblings()  | 在前序平行节点中搜索,返回列表类型,同  | 
<>.find_previous_sibling()  | 在前序平行节点中返回一个结果,同  |