BeautifulSoup基本使用

BeautifulSoup官方文档介绍:BeautifulSoup 是一个可以从HTML或XML文件中提取数据的Python库。使用BeautifulSoup更多方便,避免使用正则表达式容易出错,提高效率。

1.解析器

BeautifulSoup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是 lxml。以下为BeautifulSoup官方文档对支持的解析器优缺点对比。

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

推荐使用lxml解释器,效率更高。注意:不同的解析器返回不同的结果

2.基本使用

通过解析器,BeautifulSoup可以传入一段字符串或文件。

from bs4 import BeautifulSoup
>>> soup = BeautifulSoup("<html>data</html>")
>>> print(soup.html.string)
data

Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种: Tag , NavigableString , BeautifulSoup , Comment。接下来使用以下文档进行说明。

html_doc = """
<html><head><title>The Dormouse's story</title></head>

<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.prettify())
  • tag
    通俗来说tag就是HTML或XML文档的标签,例如上面文档的head、title、p等,如果想获取 <head> 标签,只要用 soup.head。
>>> soup.head 
<head><title>The Dormouse's story</title></head>
>>> soup.body.b
<b>The Dormouse's story</b>
>>> soup.a
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>

可以看到a点只是返回第一个,如果需要历遍全部则需要用find_all('a')。
tag有多种属性,其中两个最重要的就是name和attributes。name一般返回标签本身(soup返回document),注意,tag属性操作方法和字典一样。

>>> soup.name 
'[document]' #soup比较特殊,返回name为[doucument]
>>> soup.p.name
p 
>>> soup.p.attrs
{'class': ['title']}
>>> soup.p['class'] #可以直接修改属性soup.p['class'] = 'a'
['title']
  • NavigableString
    NavigableString就是tag标签内的内容,可以直接使用string获得内容,replace_with()进行替换。
>>> soup.p.string
"The Dormouse's story"
>>> soup.p.string.replace_with("no")
>>> soup.p.string
'no'
  • BeautifulSoup
    BeautifulSoup表示一个文档的全部内容。
  • comment
    Comment 对象是一个特殊类型的NavigableString对象,针对注释部分,输出不包括注释符号。
>>> markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"
>>> soup = BeautifulSoup(markup)
>>> soup.b.string
'Hey, buddy. Want to buy a used parser?'
>>> type(soup.b.string)
bs4.element.Comment
3.节点选择

上面说到节点选择可以直接利用标签,如<head>标签用soup.head,也可通过name和attrs可以直接获取属性,操作和字典一样。以上是直接获取的方式,当想要获取标签的子节点、父节点、兄弟节点则需要通过另外的方法。

选择 方法
直接节点 .contents和.children(生成器)
子孙节点 .descendants(生成器)
节点内容 .strings和.stripped_strings(去除空格和空行)
父节点 .parent和.parents(到根节点)
兄弟节点 .next_element(s) 和 .previous_element(s)
  • 直接子节点.contents 和 .children,子孙节点.descendants
    .contents输出方式为列表,可以通过列表索引获取某一元素。
>>> len(soup.head.contents)
1 
>>> soup.head.contents
[<title>The Dormouse's story</title>]
>>> soup.head.contents[0]
<title>The Dormouse's story</title>

.children是一个llist生成器,可以对子节点进行历遍循环

>>> soup.body.children
<list_iterator at 0x19e8183a860>
>>> for child in soup.body.children:
>>>    print(child)

.descendants是返回所有子孙节点,比较children和descendants的输出区别

>>> len(list(soup.body.descendants))
19
>>> len(list(soup.body.children))
6
>>> for child in soup.body.descendants:
>>>    print(child)
  • 节点内容.strings 和 stripped_strings
    上面基本使用说到可以使用string获得节点内容,当含有多个字符串时可以用到.string循环;当字符串含有很多空格和空行,可以用到stripped_strings去除。
>>> for string in soup.stripped_strings:
>>>    print(string)
  • 父节点.parent和.parents
    .parent是返回父节点,.parents是返回到根标签的所有节点,注意根节点<html>的父节点是BeautifulSoup 对象,BeautifulSoup 对象的父节点是None。
>>> soup.a.parent.name
'p'
>>> for parent in soup.a.parents:
>>>    if parent is None:
>>>        print(parent)
>>>    else:
>>>        print(parent.name)
p
body
html
[document]
  • 兄弟节点.next_element和 .previous_element / .next_elements和 .previous_elements
    .next_element 指向当前被解析的对象的下一个解析对象, .previous_elements当前被解析的对象的前一个解析对象。
4.搜索文档树
  • find_all

find_all( name , attrs , recursive , text , **kwargs )

  • 解释
    • name参数可以传入标签名称、正则表达式、列表。
    • text 参数接受 字符串 , 正则表达式 , 列表, True。
>>> soup.find_all('a', id="link2")
>>> soup.find_all(['a','b'])
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,841评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,415评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,904评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,051评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,055评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,255评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,729评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,377评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,517评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,420评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,467评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,144评论 3 317
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,735评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,812评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,029评论 1 256
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,528评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,126评论 2 341

推荐阅读更多精彩内容