Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库。使用它来处理HTML页面就像JavaScript代码操作HTML DOM树一样方便。官方中文文档地址

1. 安装

1.1 安装 Beautiful Soup

Beautiful Soup3 目前已经停止维护,推荐使用 Beautiful Soup4,现在已经被移植到 bs4,导入的时候需要从 bs4 导入。安装方法如下:

# 使用 pip 安装
pip install beautifulsoup4 # 使用 easy_install 安装
easy_install beautifulsoup4

1.2 安装解析器 lxml

另外还需要安装相应的解析器,lxml,html5lib 任选一个即可。

# 安装 lxml
pip install lxml # 安装 html5lib
pip install html5lib

1.3 使用方法

安装了 BeautifulSoup 以后可以导入使用。将一段文档传入BeautifulSoup 的构造方法,就能得到一个文档的对象, 可以传入一段字符串或一个文件句柄.

# 首先从 bs4 导入
from bs4 inport BeautifulSoup # 使用解析器和html文档可以初始化
soup = BeautifulSoup(open("index.html"), 'lxml')
content = '<html>data</html>'
soup = BeautifulSoup(content, 'lxml')

文档需要转换成Unicode,并且HTML的实例都被转换成Unicode编码

2. BeautifulSoup中的对象

Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,类似于浏览器中的DOM节点数,每个节点都是Python对象,所有对象可以归纳为4种: Tag , NavigableString , BeautifulSoup , Comment 。

2.1 tag 对象

tag 对象类似于一个标签节点。与XML或HTML原生文档中的标签相同,如 body,div,a,span。tag 对象有很多方法和属性。tag 对象的属性可以像字典一样进行增删改查操作。

2.1.1 name 属性

name 属性表示 tag 的名称。通过 .name 获取。如果改变了tag的name,那将影响所有通过当前Beautiful Soup对象生成的HTML文档。

2.1.2 attributes 属性

一个tag可能有很多个属性,使用 tag.attrs 获取 tag 的所有节点属性,可以对这些属性进行增删改查。获取方法如下:

  • tag.attrs:获取属性列表
  • tag.attrs[1]:获取属性列表中的第2个属性
  • tag.get('href'):获取 href 属性
  • tag['href']:获取 href 属性

2.1.3 多值属性

在HTML文档中有典型像 class 一样的有多个属性值,这些多值属性返回的值不是 string ,而是 list 。这些多值属性的节点类型如下:

  • class
  • rel
  • rev
  • accept-charset
  • headers
  • accesskey

在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

2.2 NavigableString 对象

字符串常被包含在tag内,Beautiful Soup用 NavigableString 类来包装tag中的字符串。

  • 使用 tag.string 获取 tag 内字符串,为NavigableString
  • 使用 unicode(tag.string) 转换为一般Unicode字符串
  • tag 内字符串不能编辑
  • tag.string.replace_with('content') 替换 tag 内字符串
  • tag 内字符串不支持 .contents 或 .string 属性或 find() 方法
  • 在Beautiful Soup之外使用 NavigableString 对象需要调用 unicode() 方法

2.3 BeautifulSoup 对象

BeautifulSoup 对象表示的是一个文档的全部内容。大部分时候,可以把它当作 tag 对象。

因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name。

2.4 Comment 对象

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>

3. 遍历文档树

通过遍历文档树,能够从文档中找到指定的内容。

3.1 子节点

一个 tag 可能包含多个字符串或者其他 tag,这些 tag 就是顶层的子节点,Beautiful Soup提供了许多操作和遍历子节点的属性。需要注意:

  • 字符串没有子节点。
  • BeautifulSoup 对象本身一定会包含子节点

假设有以下几种简单的方式获取子节点:

  • 使用tag名:获取第一个直接子节点:soup.div.p
  • 使用contents属性:获取所有直接子节点列表:soup.div.contents
  • 使用children属性: 对子节点进行循环:soup.div.children
  • 使用descendants属性:所有tag的子孙节点进行递归循环:soup.div.descendants
  • 使用string属性:获取只有一个string子节点tag的子节点:p.string
  • 使用strings属性:循环有多个string子节点的情况:div.strings
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)

3.2 父节点

每个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.3 兄弟节点

兄弟节点就是具有相同父节点的同义词节点。如3.1中定义的 div_html 中的3个p标签互相为兄弟节点。使用下面的节点tag属性访问兄弟节点

  • next_sibling:当前节点的下一个兄弟节点
  • previous_sibling:当前节点的上一个兄弟节点
  • next_siblings:当前节点之后的所有兄弟节点
  • previous_siblings:当前节点之前的所有兄弟节点

4. 搜索文档树

搜索功能可以说是写爬虫过程中必用的功能,用来查找指定的节点,Beautiful Soup定义了很多搜索方法,这些搜索方法的参数和用法都很类似,查询功能非常强大,下面主要针对 find_all 方法说明。

4.1 过滤器

过滤器是使用搜索方法过程中的匹配规则,即参数的可能取值。过滤器可以为下面几种形式:

  • 字符串:find_all('div')
  • 列表:find_all(['div', 'span'])
  • 正则表达式:find_all(re.compile('[a-z]{1,3}'))
  • True:匹配任意非字符串子节点
  • 方法:相当于匹配的回调函数,该方法返回 True 表示匹配
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属性的节点

4.2 find_all() find() 方法

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)

各参数含义如下:

  • name:匹配 tag 标签名
  • attrs:匹配属性名:find_all(href='index.html')
  • text:匹配文档中的字符串内容
  • limit:指定匹配的结果集数量
  • recursive:默认True,False表示只搜索直接子节点

以上的参数值都可以是 4.1 中说明的任意一种过滤器值。另外还需要注意以下几点:

  • attrs 参数为字典类型,可以是多个属性条件组合
  • 单独使用 class 属性时,应该使用 class_
  • class 属性为多值属性,会分别搜索每个 CSS 类名
  • 按照CSS类目完全匹配时,必须顺序相同
# 搜索所有 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)

4.3 其他方法

其他的搜索方法参数和 find_all 和 find 类似,它们成对出现,分别返回结果列表和第一个匹配的结果,只是搜索文档的范围不一样,下面列举一些常用的:

  • 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():从当前节点之前的节点搜索

4.4 CSS选择器

Beautiful Soup支持大部分的CSS选择器,使用 select() 方法来搜索。如id选择器,标签选择器,属性选择器设置组合选择器。如:

  • soup.select('body a')
  • soup.select('#top')
  • soup.select('div > span')
  • soup.select('.button + img')

5. 修改文档树

当我们得到搜索结果以后,希望搜索结果中的某些节点不参与之后的搜索,那么就需要把这些节点删除掉,这就需要对文档树修改。修改的方法如下:

  • append():向当前tag中添加内容(string)
  • new_tag(),new_string():添加一段文本
  • insert(index, content):在 index 位置插入属性
  • insert_before() 和 insert_after():在当前节点前后插入内容
  • clear():移除当前节点内容
  • extract();将当前tag移除文档树,并作为结果返回
  • decompose():将当前节点移除文档树并完全销毁
  • replace_with():移除文档树中的某段内容,并用新tag或文本节点替代它
  • wrap():对指定的tag元素进行包装,并返回包装后的结果

6. 输出

有时候,需要对查到的或者修改过的文档树展示或者保存。

prettify() 方法将Beautiful Soup的文档树格式化后以Unicode编码输出,每个XML/HTML标签都独占一行。BeautifulSoup 对象和它的tag节点都可以调用 prettify() 方法。

可以对一个 BeautifulSoup 对象或 Tag 对象使用Python的 unicode() 或 str() 方法,从而对输出结果进行压缩。

原文地址:http://uusama.com/467.html

Python爬虫利器:Beautiful Soup的更多相关文章

  1. python 爬虫利器 Beautiful Soup

    python 爬虫利器 Beautiful Soup Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文 ...

  2. Python爬虫之Beautiful Soup解析库的使用(五)

    Python爬虫之Beautiful Soup解析库的使用 Beautiful Soup-介绍 Python第三方库,用于从HTML或XML中提取数据官方:http://www.crummv.com/ ...

  3. [Python爬虫] 使用 Beautiful Soup 4 快速爬取所需的网页信息

    [Python爬虫] 使用 Beautiful Soup 4 快速爬取所需的网页信息 2018-07-21 23:53:02 larger5 阅读数 4123更多 分类专栏: 网络爬虫   版权声明: ...

  4. python爬虫之Beautiful Soup基础知识+实例

    python爬虫之Beautiful Soup基础知识 Beautiful Soup是一个可以从HTML或XML文件中提取数据的python库.它能通过你喜欢的转换器实现惯用的文档导航,查找,修改文档 ...

  5. python爬虫之Beautiful Soup的基本使用

    1.简介 简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据.官方解释如下: Beautiful Soup提供一些简单的.python式的函数用来处理导航.搜索 ...

  6. Python爬虫库-Beautiful Soup的使用

    Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库,简单来说,它能将HTML的标签文件解析成树形结构,然后方便地获取到指定标签的对应属性. 如在上一篇文章通过爬虫 ...

  7. python 爬虫5 Beautiful Soup的用法

    1.创建 Beautiful Soup 对象 from bs4 import BeautifulSoup html = """ <html><head& ...

  8. Python爬虫之Beautiful Soup库的基本使用

  9. Python爬虫利器二之Beautiful Soup的用法

    上一节我们介绍了正则表达式,它的内容其实还是蛮多的,如果一个正则匹配稍有差池,那可能程序就处在永久的循环之中,而且有的小伙伴们也对写正则表达式的写法用得不熟练,没关系,我们还有一个更强大的工具,叫Be ...

  10. python爬虫利器Selenium使用详解

    简介: 用pyhon爬取动态页面时普通的urllib2无法实现,例如下面的京东首页,随着滚动条的下拉会加载新的内容,而urllib2就无法抓取这些内容,此时就需要今天的主角selenium. Sele ...

随机推荐

  1. Nginx功能展示实验

    Nginx功能展示实验 Nging可以作为反代服务器:也可以作为负载均衡器,并自带根据对后端服务器健康状态检测具有增删服务器的功能:也可以作为纯Web服务器,提供Web服务. 本实验将使用Nginx实 ...

  2. Redis 学习笔记-5种数据类型的基本操作

    1.string类型 基本操作列表: GET 获取指定键对应的值 SET 设定键值 DEL 删除指定键对应的值(对所有数据类型都有效) > set hello world OK > get ...

  3. LeetCode 106. Construct Binary Tree from Inorder and Postorder Traversal (用中序和后序树遍历来建立二叉树)

    Given inorder and postorder traversal of a tree, construct the binary tree. Note:You may assume that ...

  4. 0_Simple__clock + 0_Simple__clock_nvrtc

    使用 clock() 函数在CUDA核函数内部进行计时,将核函数封装为PTX并在另外的代码中读取和使用. ▶ 源代码:文件内建核函数计时. #include <stdio.h> #incl ...

  5. 注销/etc/passwd带来的系统登陆不上

    今天在修改虚拟机密码上的时候,将/etc/passwd中root所在的哪行注销掉了,想象是注销了,root登陆时应该不要输入密码,结果是系统进度条走到最后的时候 进入不了系统了. 结果去普及了下/et ...

  6. C# linq左连接与分组

    1.左连接使用DefaultIfEmpty(): 2.分组时候判断newper.FirstOrDefault() == null ? null: newper.ToList()这个经常出错误,如果不判 ...

  7. shadow dom 隔离代码 封装

    Shadow DOM是指浏览器的一种能力,它允许在文档(document)渲染时插入一棵DOM元素子树,但是这棵子树不在主DOM树中.   Shadow DOM 解决了 DOM 树的封装问题.     ...

  8. phpstorm2016.3+xdebug调试

    1.首先打开PHP配置文件,php.in修改相关xedebug配置 ; XDEBUG Extension [xdebug] zend_extension ="d:/wamp64/bin/ph ...

  9. 三元运算符2>1?true:false;

    1.说明: xxx?xxx:xxx; 第一个'xxx'是写条件语句,条件自己根据需求定 第二个'xxx'是当条件为真时会得到的值 第三个'xxx'是当条件为假时会得到的值 2.例子: 代码: bool ...

  10. 在LINQ查询中LINQ之Group By的用法

    LINQ定义了大约40个查询操作符,如select.from.in.where.group 以及order by,借助于LINQ技术,我们可以使用一种类似SQL的语法来查询任何形式的数据.Linq有很 ...