Beautiful Soup 是一个能够从HTML或XML文件中提取数据的Python库。使用它来处理HTML页面就像JavaScript代码操做HTML DOM树同样方便。官方中文文档地址css
Beautiful Soup3 目前已经中止维护,推荐使用 Beautiful Soup4,如今已经被移植到 bs4,导入的时候须要从 bs4 导入。安装方法以下:html
# 使用 pip 安装 pip install beautifulsoup4 # 使用 easy_install 安装 easy_install beautifulsoup4
另外还须要安装相应的解析器,lxml,html5lib 任选一个便可。html5
# 安装 lxml pip install lxml # 安装 html5lib pip install html5lib
安装了 BeautifulSoup 之后能够导入使用。将一段文档传入BeautifulSoup 的构造方法,就能获得一个文档的对象, 能够传入一段字符串或一个文件句柄.node
# 首先从 bs4 导入 from bs4 inport BeautifulSoup # 使用解析器和html文档能够初始化 soup = BeautifulSoup(open("index.html"), 'lxml') content = '<html>data</html>' soup = BeautifulSoup(content, 'lxml')
文档须要转换成Unicode,而且HTML的实例都被转换成Unicode编码python
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,相似于浏览器中的DOM节点数,每一个节点都是Python对象,全部对象能够概括为4种: Tag , NavigableString , BeautifulSoup , Comment 。正则表达式
tag 对象相似于一个标签节点。与XML或HTML原生文档中的标签相同,如 body,div,a,span。tag 对象有不少方法和属性。tag 对象的属性能够像字典同样进行增删改查操做。浏览器
name 属性表示 tag 的名称。经过 .name 获取。若是改变了tag的name,那将影响全部经过当前Beautiful Soup对象生成的HTML文档。app
一个tag可能有不少个属性,使用 tag.attrs 获取 tag 的全部节点属性,能够对这些属性进行增删改查。获取方法以下:函数
在HTML文档中有典型像 class 同样的有多个属性值,这些多值属性返回的值不是 string ,而是 list 。这些多值属性的节点类型以下:编码
在XML文档中没有多值属性
content = '<a href="index.html" class="button button-blue" data="1 2 3"></a>' soup = BeautifulSoup(content, 'lxml') tag = soup.a # 获取 a 标签 tag.name # 标签名称:a tag.attrs # 属性列表:['href', 'class', 'data'] tag.get('href') # 获取href属性:index.html tag['class'] # 获取class属性为list:[button,button-blue] tag['data'] # data属性的值为string:1 2 3
字符串常被包含在tag内,Beautiful Soup用 NavigableString 类来包装tag中的字符串。
BeautifulSoup 对象表示的是一个文档的所有内容。大部分时候,能够把它看成 tag 对象。
由于 BeautifulSoup 对象并非真正的HTML或XML的tag,BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name。
Comment 对象是一个特殊类型的 NavigableString 对象,用来表示文档的注释部分。
markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>" soup = BeautifulSoup(markup) comment = soup.b.string type(comment) # <class 'bs4.element.Comment'> print(soup.b.prettify()) # <b> # <!--Hey, buddy. Want to buy a used parser?--> # </b>
经过遍历文档树,可以从文档中找到指定的内容。
一个 tag 可能包含多个字符串或者其余 tag,这些 tag 就是顶层的子节点,Beautiful Soup提供了许多操做和遍历子节点的属性。须要注意:
假设有如下几种简单的方式获取子节点:
div_html = ' <div> <p>uu</p> <p>sa</p> <p> <a>ma</a> --> </p> </div>' soup = BeautifulSoup(div_html), 'lxml') div = soup.div # 获取 div 节点 div.p # <p>uu</p> div.contents # [<p>uu</p>, <p>sa</p>, <p><a>ma</a>--></p>] div.contents[0] # <p>uu</p> for child in div.children: print(child) # <p>uu</p><p>sa</p><p><a>ma</a>--></p> for child in div.descendants: pring(child)
每一个tag或字符串都有父节点,即每一个节点都被包含在tag中,经过 .parent 属性来获取某个元素的父节点: p.parent,经过元素的 .parents 属性能够递归获得元素的全部父辈节点。
soup = BeautifulSoup(div_html), 'lxml') # 使用3.1中定义的 div_html div = soup.div # 获取 div 节点 sa = div.a.string # 第一个 a 节点的string sa.parent # a 节点 sa.parent.parent # div 节点 for parent in sa.parents: print(parent) # a # div # [document] # None
兄弟节点就是具备相同父节点的同义词节点。如3.1中定义的 div_html 中的3个p标签互相为兄弟节点。使用下面的节点tag属性访问兄弟节点
搜索功能能够说是写爬虫过程当中必用的功能,用来查找指定的节点,Beautiful Soup定义了不少搜索方法,这些搜索方法的参数和用法都很相似,查询功能很是强大,下面主要针对 find_all 方法说明。
过滤器是使用搜索方法过程当中的匹配规则,即参数的可能取值。过滤器能够为下面几种形式:
content = '<nav><a>a_1</a><a>a_2</a>string</nav>' soup = BeautifulSoup(content), 'lxml') nav_node = soup.nav # <nav><a>a_1</a><a>a_2</a>string</nav> nav_node.find_all(True) # 不匹配 string # ['<a>a_1</a>', '<a>a_2</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) # 返回有class属性没有id属性的节点
find_all 方法返回匹配搜索的全部节点的列表或者空,而 find 方法直接返回第一个匹配搜索的结果。详细的定义以下:
find_all(name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs) find_find(name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs)
各参数含义以下:
以上的参数值均可以是 4.1 中说明的任意一种过滤器值。另外还须要注意如下几点:
# 搜索全部 div 标签 soup.find_all('div') # 搜索全部具备id属性而且id属性值为 link1 或者 link2 的节点 soup.find_all(id=['link1', 'link2']) # 搜索全部 class 属性包含 button 的节点 soup.find_all(class_='button') # 搜索全部匹配给定正则表达式内容的 p 标签 soup.find_all('p', text=re.compile('game')) # 搜索具备 button 类,而且具备值为 link1 的 href 属性的 a 标签 soup.find_all('a', {'classl': 'button', 'href': 'link1'}) # 只搜索一个直接子节点的 a 标签 soup.find_all('a', limit=1, recursive=False)
其余的搜索方法参数和 find_all 和 find 相似,它们成对出现,分别返回结果列表和第一个匹配的结果,只是搜索文档的范围不同,下面列举一些经常使用的:
Beautiful Soup支持大部分的CSS选择器,使用 select() 方法来搜索。如id选择器,标签选择器,属性选择器设置组合选择器。如:
当咱们获得搜索结果之后,但愿搜索结果中的某些节点不参与以后的搜索,那么就须要把这些节点删除掉,这就须要对文档树修改。修改的方法以下:
有时候,须要对查到的或者修改过的文档树展现或者保存。
prettify() 方法将Beautiful Soup的文档树格式化后以Unicode编码输出,每一个XML/HTML标签都独占一行。BeautifulSoup 对象和它的tag节点均可以调用 prettify() 方法。
能够对一个 BeautifulSoup 对象或 Tag 对象使用Python的 unicode() 或 str() 方法,从而对输出结果进行压缩。