栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Beautiful Soup 采坑之旅

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Beautiful Soup 采坑之旅

Beautiful Soup入门

Beautiful Soup是一个Python库,用来解析html和xml结构的文档。具体关于Beautiful Soup的介绍与使用,可以参考以下资料:

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

Beautiful Soup 4.2.0 中文文档

下面是我在使用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格式的文档
速度慢
不依赖外部扩展

首先,如果是解析从网页上爬下来的HTML文档,请不要使用lxml XML 解析器,因为HTML解析器和XML解析器对于一文档的解析方式是不同的。比如对于空标签,因为空标签不符合HTML标准,所以解析器把它解析成,而使用XML解析时,空标签依然被保留。

其次,在Python2.7.3之前的版本和Python3中3.2.2之前的版本中,标准库中内置的HTML解析方法不够稳定,所以我推荐使用lxml或者html5lib作为html文档的解析器,因为容错性比较好。

在HTML或XML文档格式正确的情况下,不同解析器的差别只是解析速度的差别。而在很多情况下,我们从网页上爬取的HTML文档会有格式不严谨的地方,那么在不同的解析器中返回的结果可能是不一样的,此时用户需要选择合适的解析器来满足自己的需求。

# lxml解析BeautifulSoup("

", "lxml")#                      未补全BeautifulSoup("

", "lxml")# 

              补全# html5lib库解析BeautifulSoup("

", "html5lib")# 

 补全BeautifulSoup("

", "html5lib")# 

 补全#Python内置库解析BeautifulSoup("

", "html.parser")  #                                                未补全BeautifulSoup("

", "html.parser")# 

                                        补全

从上面的例子可以看出,html5lib对于文档的容错性是最好的,它能补全大多数的标签。而lxml和python内置解析器会忽略结束标签,补全开始标签。

而对于部分没有结束标签的标签比如、等,在正常情况下,解析器都会正确解析,但如果是漏掉'/'的情况下,例如:

# lxml解析BeautifulSoup("", "lxml")#                  补全# html5lib库解析BeautifulSoup("", "html5lib")#     补全#Python内置库解析BeautifulSoup("", "html.parser")#                                     未补错误

可见,Python内置库解析无法正确补全不需要结束标签的标签,比如

find_all()的attrs参数

在find_all()方法中,如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索。如传入 href 参数,Beautiful Soup会搜索每个tag的”href”属性:

soup.find_all(href=re.compile("elsie"))# [Elsie]

假如我们想用 class 过滤,不过 class 是 python 的关键词,这怎么办?加个下划线就可以

soup.find_all("a", class_="sister")# [Elsie,#  Lacie,#  Tillie]

但有些tag属性在搜索不能使用,比如HTML5中的 data-* 属性,同时name由于已经是find_all()方法中的一个参数名(代表tag的名字),所以也不可通过tag中的name属性来搜索tag,但是可以通过 find_all() 方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的tag,例如:

data_soup.find_all(attrs={"data-foo": "value"})# [foo!]
.string 和 get_text()的区别

在Beautiful Soup,有两种获取标签内容的方法:.string属性 和 get_text()方法。

  • .string 用来获取标签的内容 ,返回一个 NavigableString 对象。

    • 如果tag只有一个 NavigableString 类型子节点,那么这个tag可以使用 .string 得到子节点。

    • 如果一个tag仅有一个子节点,那么这个tag也可以使用 .string 方法,输出结果与当前唯一子节点的 .string 结果相同。

    • 如果tag包含了多个子节点,tag就无法确定 .string 方法应该调用哪个子节点的内容, .string 的输出结果是 None。

  • get_text() 用来获取标签中所有字符串包括子标签的内容,返回的是 unicode 类型的字符串

实际场景中我们一般使用 get_text 方法获取标签中的内容。

.next_sibling 和 find_next_sibling()

在文档树中,使用 .next_sibling 和 .previous_sibling 属性来查询兄弟节点。实际文档中的tag的 .next_sibling 和 .previous_sibling 属性通常是字符串或空白。例如:

ElsieLacieTillie

如果以为第一个标签的 .next_sibling 结果是第二个标签,那就错了,真实结果是第一个标签和第二个标签之间的顿号和换行符:

link = soup.a
link# Elsielink.next_sibling# u',n'link.next_sibling.next_sibling# Lacie

所以我建议使用 find_next_sibling() 方法来查询兄弟节点:

link.find_next_sibling("a")# Lacielink.find_next_siblings("a")# [Lacie,# Tillie]
换行符的问题

在HTML文档中经常会出现一些用来换行
标签,比如:

  some text 
   some more text  
   and more text 

Beautiful Soup会将其自动补全为以下错误的形式:

  some text  
     some more text      
       and more text      
  

因为
标签是为了展示的美观而出现的,而我们在解析文档时,这种标签的出现会影响我们解析的正确性(就如上面那个例子所示)。为了解决这个问题,我们需要使用extract()方法将文档中的
标签删掉

soup = BeautifulSoup(text)for linebreak in soup.find_all('br'):
    linebreak.extract()

这样最终的文档格式就变为:

  some text     some more text 
     and more text 
大小写问题

因为HTML标签是大小写敏感的,所以3种解析器再出来文档时都将tag和属性转换成小写。例如文档中的 会被转换为 。如果想要保留tag的大写的话,那么应该将文档 解析成XML。

参考资料
  • Beautiful Soup 4.2.0 中文文档

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

  • python爬虫入门教程--HTML文本的解析库BeautifulSoup(四)

  • Beautifulsoup sibling structure with br tags

  • (学习笔记)Python BeautifulSoup4 取值部分


文章标题:Beautiful Soup 采坑之旅
文章作者:Ciel Ni
文章链接:http://www.cielni.com/2018/06/14/beautifulsoup/





转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号