【3】数据筛选3 - BeautifulSoup4


目录


    1. 开发前准备
    2. 不同解析器对比
    3. BeautifulSoup4 初始化和节点对象的认识
    4. BS4 案例操作:初始化对象文档
    5. 节点查询:子节点
    6. 节点查询:父节点
    7. 节点查询:兄弟节点
    8. 节点查询:解析顺序
    9. 高级查询: find/find_all 检索
    10. 高级查询: CSS 选择器



1.开发前准备

  • 官方文档: https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.html
    官方文档中文版: https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/
  • 命令安装方式
    pip install beautifulsoup4
    easy_install beautifulsoup4
    下载源码包(tar.gz)安装
    python setup.py install
  • 安装解析器: BeautifulSoup4 本身只包含解析器接口规则,支持 python 内置的 HTML 解析器,同时支持第三方的一些解析器[如 lxml]
  • 如果使用过程中没有指定使用解析器, BeautifulSoup4 会自动从当前的 python 环境中检索最优的解析器加载使用
    pip install lxml
    or
    pip install html5lib


2.不同解析器对比

解析器 使用 优缺点
标准库 BeautifulSoup(html, ‘html.parser’) 优点:内置标准库、执行速度适中、容错能力强.
缺点:对中文解析的容错能力有限
lxml BeautifulSoup(html, ‘lxml’) 优点:速度快,容错能力强
缺点:需要安装 c 语言库
lxml BeautifulSoup(html, [‘lxml’, ‘xml’]) 唯一支持 XML 的解析器
html5lib BeautifulSoup(html, ‘html5lib’) 优点:容错能力最好, 浏览器方式解析文档, 生成 H5 格式的文档
缺点:速度慢,不依赖外部扩展
  • 综上所述,优先推荐使用 lxml 解析器


3.BeautifulSoup4 初始化和节点对象的认识

  • BeautifulSoup4(BS4)可以将一个 html 文档数据流或者 html 文档对象或者 html 字符串,直接加载到 BS4 对象中,得到一个 BS4 的文档对象
    --- from bs4 import BeautifulSoup
    --- soup = BeautifulSoup(open(‘index.html’))
    --- soup = BeautifulSoup(‘<html>……</html>’)
  • BeautifulSoup4 将 HTML 结构化文档, 解析为树形结构化数据,树形文档对象中主要包含四种对象
    --- tag: 标签节点对象节点
    --- name: 标签名称对象节点
    --- attributes: 标签属性对象节点, like dict,如果是多值属性,属性对应的值就是一个 list 数据
    --- NavigateString: 标签中文本对象节点,可以直接通过 unicode()函数将文本转换成 unicode 字符串


4.BS4 案例操作:初始化对象文档

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<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>
</body>
</html>
"""
from bs4 import BeautifulSoup
# 构建 bs4 文档对象
soup = BeautifulSoup(html_doc, 'lxml')
print(type(soup)) # <class 'bs4.BeautifulSoup'>


5.节点查询: 子节点

# 节点名称查询
print(soup.title) # <title>The Dormouse's story</title>
print(soup.p) # <p class="title"><b>The Dormouse's story</b></p>
print(soup.a) # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
# 子节点查询
chs = soup.contents
print(type(chs), len(chs)) # <class 'list'> 2
chs2 = soup.children
print(type(chs2), len(list(chs2))) # <class 'list_iterator'> 2
# 包含节点查询
chs3 = soup.descendants
print(type(chs3), len(list(chs3))) # <class 'generator'> 28
# 子节点内容获取
# 获取节点内部文本数据
print(soup.title.string) # The Dormouse's story
# 获取文本节点的文本数据
print(soup.title.contents[0].string) # The Dormouse's story
# 如果包含子节点并且不是文本节点,返回 None
print(soup.body.string) # None
# 获取包含的所有文本数据,包括空白字符
print(soup.body.strings) # <generator object Tag._all_strings at 0x0000021B6360F6D8>
# 获取包含的所有文本数据,剔除空白字符
print(soup.body.stripped_strings) # <generator object Tag.stripped_strings at 0x0000022BBB38F6D8>


6.节点查询:父节点

# ##########################父节点查询

print(soup.a) # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
# 查询直接父节点
print(soup.a.parent.name) # p
# 遍历查询所有父节点
print([tag.name for tag in soup.a.parents]) # ['p', 'body', 'html', '[document]']


7.节点查询: 兄弟节点

# ##########################兄弟节点

# 获取当前节点
print(soup.a) # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
# 获取前一个兄弟节点:得到文本节点
print(soup.a.previous_sibling) # Once upon a time there were three little sisters; and their
names were
# 获取后一个兄弟节点:得到文本节点
print(soup.a.next_sibling) #,
# 获取所有的前面的兄弟节点:得到所有紧跟当前节点前面的兄弟节点的生成器对象
print(soup.a.previous_siblings) # <generator object PageElement.previous_siblings at
0x000001EF06B57750>
# 获取所有的后面的兄弟节点:得到所有紧跟当前节点后面的兄弟节点的生成器对象
print(soup.a.next_siblings) # <generator object PageElement.next_siblings at 0x0000018A1B41F6D8>


8.节点查询:解析顺序

BeautifulSoup4 提供了一种比较特殊的操作:按照文档的解析顺序进行节点的查询,解析顺序和浏览器解释 HTML 文档的顺序是一致的

# #########################解析顺序节点

#获取当前节点
print(soup.a) # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
# 获取前一个兄弟节点:得到文本节点
print(soup.a.previous_element) # Once upon a time there were three little sisters; and their
names were
# 获取后一个兄弟节点:得到文本节点
print(soup.a.next_element) #Elsie
# 获取所有的前面的兄弟节点:得到所有紧跟当前节点前面的兄弟节点的生成器对象
print(soup.a.previous_elements) # <generator object PageElement.previous_elements at
0x0000013EC8C9F6D8>
# 获取所有的后面的兄弟节点:得到所有紧跟当前节点后面的兄弟节点的生成器对象
print(soup.a.next_elements) # <generator object PageElement.next_elements at 0x0000013EC8C9F6D8>
# 获取解析过程节点顺序
print([tag.name if tag.name else tag for tag in soup.html.next_elements])

➔ 解析结果:

 ['head', 'title', "The Dormouse's story", '\n', 'body', '\n', 'p', 'b', "The Dormouse's story", '\n',
'p', 'Once upon a time there were three little sisters; and their names were\n', 'a', 'Elsie', ',\n', 'a',
'Lacie', ' and\n', 'a', 'Tillie', ';\nand they lived at the bottom of a well.', '\n', 'p', '...', '\n', '\n',
'\n']


9.高级查询: find/find_all 检索

  • find(name, attrs, recursive, text, **kwargs)
    ◼ 查询得到一个节点对象数据,如果结果不存在返回 None
    ◼ param name: 要查询的标签的名称
    ◼ param attrs: 要查询的属性字典,如{‘class’: ‘title’}
    ◼ param recursive: 是否查询所有包含的节点,默认 True
    ◼ param text: 查询的节点中包含的指定的内容
    ◼ param kwargs: 如果查询的属性不是内置的指定的属性,可以通过 kwargs 添加自定义属性
  • find_all(name, attrs, recursive, text, limit, **kwargs)
    ◼ 查询得到一组节点对象数据,如果结果不存在返回[]
    ◼ param limit:查询的结果数量限制
    ◼ 其他参数参考 find(..)
  • 查询过滤操作
    ◼ 条件查询: find_all(‘p’, {‘class’: ‘title’})
    ◼ 并且查询: find_all([‘p’, ‘a’])
    ◼ 属性查询: find_all(id=’link2’)
    ◼ 正则查询: find_all(text=re.compile(‘sisters’))
    ◼ 指定属性查询: find_all(class_=’sister’)
  • 其他查询
    ◼ find_parent()/find_parents()
    ◼ find_previous_sibling()/find_previous_siblings()/find_next_sibling()/find_next_siblings()
    ◼ find_next()/find_all_next()/find_previous()/find_all_previous()


10. 高级查询: CSS 选择器

  • beautifulsoup.select(css syntax)
# ##########################css 查询

print(soup.select("title")) # 标签选择器
print(soup.select("#link1")) # id 选择器
print(soup.select(".sister")) # class 选择器
print(soup.select("p > a")) # 子类选择器
print(soup.select("p a")) # 包含选择器
print(soup.select("p, a, b")) # 群组选择器
print(soup.select("#link1 ~ .sister")) # 兄弟选择器
print(soup.select("#link1 + .sister")) # 兄弟选择器
print(soup.select("p[class='title']")) # 属性选择器
print(soup.select("a:nth-of-type(2)")) # 伪类选择器
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容

  • Beautiful Soup是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实...
    LitOrange阅读 5,269评论 0 4
  • 声明:本文讲解的实战内容,均仅用于学习交流,请勿用于任何商业用途! 一、前言 强烈建议:请在电脑的陪同下,阅读本文...
    Bruce_Szh阅读 12,700评论 6 28
  • 我想写诗, 可生活告诉我, 你不可以拥有诗人的情怀。 但倔强的我依旧追寻诗的方向。 我欲下笔, 可稿纸告诉我, 你...
    三流烟客阅读 266评论 0 1
  • 【日精进打卡第194天】 【知-学习】 1、背诵大纲2遍,大学2遍 【经典名句分享】 不以物喜,不以己悲 【行-实...
    吴佳妮_ab17阅读 99评论 0 0
  • 我听到了你的惴惴不安 像是烈日灼痛路人的神经 快点涂些隔离霜吧 音乐不会因为失效而变得焦躁不堪 让那些冷嘲热讽的观...
    泡沫之夏音乐会阅读 219评论 0 1