Python下利用BeautifulSoup解析HTML

摘要

Beautiful Soup 是一个可以从 HTML 或 XML 格式文件中提取数据的 Python 库,他可以将HTML 或 XML 数据解析为Python 对象,以方便通过Python代码进行处理。

文档环境

  • 本文档中代码的测试环境

Beautifu Soup 使用说明

Beautiful Soup 的基本功能就是对HTML的标签进行查找及编辑。

基本概念-对象类型

Beautiful Soup 将复杂 HTML 文档转换成一个复杂的树形结构,每个节点都被转换成一个Python 对象,Beautiful Soup将这些对象定义了4 种类型: Tag、NavigableString、BeautifulSoup、Comment 。

对象类型 描述
BeautifulSoup 文档的全部内容
Tag HTML的标签
NavigableString 标签包含的文字
Comment 是一种特殊的NavigableString类型,当标签中的NavigableString 被注释时,则定义为该类型

安装及引用

# Beautiful Soup
pip install bs4

# 解析器
pip install lxml
pip install html5lib
# 初始化
from bs4 import BeautifulSoup

# 方法一,直接打开文件
soup = BeautifulSoup(open("index.html"))

# 方法二,指定数据
resp = "<html>data</html>"
soup = BeautifulSoup(resp, ‘lxml‘)

# soup 为 BeautifulSoup 类型对象
print(type(soup))

标签搜索及过滤

基本方法

标签搜索有find_all() 和find() 两个基本的搜索方法,find_all() 方法会返回所有匹配关键字的标签列表,find()方法则只返回一个匹配结果。

soup = BeautifulSoup(resp, ‘lxml‘)

# 返回一个标签名为"a"的Tag
soup.find("a")

# 返回所有tag 列表
soup.find_all("a")

## find_all方法可被简写
soup("a")

#找出所有以b开头的标签
for tag in soup.find_all(re.compile("^b")):
    print(tag.name)

#找出列表中的所有标签
soup.find_all(["a", "p"])

# 查找标签名为p,class属性为"title"
soup.find_all("p", "title")

# 查找属性id为"link2"
soup.find_all(id="link2")

# 查找存在属性id的
soup.find_all(id=True)

#
soup.find_all(href=re.compile("elsie"), id=‘link1‘)

#
soup.find_all(attrs={"data-foo": "value"})

#查找标签文字包含"sisters"
soup.find(string=re.compile("sisters"))

# 获取指定数量的结果
soup.find_all("a", limit=2)

# 自定义匹配方法
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)

# 仅对属性使用自定义匹配方法
def not_lacie(href):
        return href and not re.compile("lacie").search(href)
soup.find_all(href=not_lacie)

# 调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False 

soup.find_all("title", recursive=False)

扩展方法

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() 之前的第一个元素

CSS选择器

Beautiful Soup支持大部分的CSS选择器 http://www.w3.org/TR/CSS2/selector.html, 在 Tag 或 BeautifulSoup 对象的 .select() 方法中传入字符串参数, 即可使用CSS选择器的语法找到tag。

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>
"""

soup = BeautifulSoup(html_doc)

# 所有 a 标签
soup.select("a")

# 逐层查找
soup.select("body a")
soup.select("html head title")

# tag标签下的直接子标签
soup.select("head > title")
soup.select("p > #link1")

# 所有匹配标签之后的兄弟标签
soup.select("#link1 ~ .sister")

# 匹配标签之后的第一个兄弟标签
soup.select("#link1 + .sister")

# 根据calss类名
soup.select(".sister")
soup.select("[class~=sister]")

# 根据ID查找
soup.select("#link1")
soup.select("a#link1")

# 根据多个ID查找
soup.select("#link1,#link2")

# 根据属性查找
soup.select(‘a[href]‘)

# 根据属性值查找
soup.select(‘a[href^="http://example.com/"]‘)
soup.select(‘a[href$="tillie"]‘)
soup.select(‘a[href*=".com/el"]‘)

# 只获取一个匹配结果
soup.select(".sister", limit=1)

# 只获取一个匹配结果
soup.select_one(".sister")

标签对象方法

标签属性

soup = BeautifulSoup(‘<p class="body strikeout" id="1">Extremely bold</p><p class="body strikeout" id="2">Extremely bold2</p>‘)
# 获取所有的 p标签对象
tags = soup.find_all("p")
# 获取第一个p标签对象
tag = soup.p
# 输出标签类型
type(tag)
# 标签名
tag.name
# 标签属性
tag.attrs
# 标签属性class 的值
tag[‘class‘]
# 标签包含的文字内容,对象NavigableString 的内容
tag.string

# 返回标签内所有的文字内容
for string in tag.strings:
    print(repr(string))

# 返回标签内所有的文字内容, 并去掉空行
for string in tag.stripped_strings:
    print(repr(string))

# 获取到tag中包含的所有及包括子孙tag中的NavigableString内容,并以Unicode字符串格式输出
tag.get_text()
## 以"|"分隔
tag.get_text("|")
## 以"|"分隔,不输出空字符
tag.get_text("|", strip=True)

获取子节点

tag.contents  # 返回第一层子节点的列表
tag.children  # 返回第一层子节点的listiterator 对象
for child in tag.children:
    print(child)

tag.descendants # 递归返回所有子节点
for child in tag.descendants:
    print(child)

获取父节点

tag.parent # 返回第一层父节点标签
tag.parents # 递归得到元素的所有父辈节点

for parent in tag.parents:
    if parent is None:
        print(parent)
    else:
        print(parent.name)

获取兄弟节点

# 下一个兄弟元素
tag.next_sibling 

# 当前标签之后的所有兄弟元素
tag.next_siblings
for sibling in tag.next_siblings:
    print(repr(sibling))

# 上一个兄弟元素
tag.previous_sibling

# 当前标签之前的所有兄弟元素
tag.previous_siblings
for sibling in tag.previous_siblings:
    print(repr(sibling))

元素的遍历

Beautiful Soup中把每个tag定义为一个“element”,每个“element”,被自上而下的在HTML中排列,可以通过遍历命令逐个显示标签

# 当前标签的下一个元素
tag.next_element

# 当前标签之后的所有元素
for element in tag.next_elements:
    print(repr(element))

# 当前标签的前一个元素
tag.previous_element
# 当前标签之前的所有元素
for element in tag.previous_elements:
    print(repr(element))

修改标签属性

soup = BeautifulSoup(‘<b class="boldest">Extremely bold</b>‘)
tag = soup.b

tag.name = "blockquote"
tag[‘class‘] = ‘verybold‘
tag[‘id‘] = 1

tag.string = "New link text."
print(tag)

修改标签内容(NavigableString)

soup = BeautifulSoup(‘<b class="boldest">Extremely bold</b>‘)
tag = soup.b
tag.string = "New link text."

添加标签内容(NavigableString)

soup = BeautifulSoup("<a>Foo</a>")
tag = soup.a
tag.append("Bar")
tag.contents

# 或者

new_string = NavigableString("Bar")
tag.append(new_string)
print(tag)

添加注释(Comment)

注释是一个特殊的NavigableString 对象,所以同样可以通过append() 方法进行添加。

from bs4 import Comment
soup = BeautifulSoup("<a>Foo</a>")
new_comment = soup.new_string("Nice to see you.", Comment)
tag.append(new_comment)
print(tag)

添加标签(Tag)

添加标签方法有两种,一种是在指定标签的内部添加(append方法),另一种是在指定位置添加(insert、insert_before、insert_after方法)

  • append方法

    
    soup = BeautifulSoup("<b></b>")
    tag = soup.b
    new_tag = soup.new_tag("a", href="http://www.example.com")
    new_tag.string = "Link text."
    tag.append(new_tag)
    print(tag)
* insert方法,是指在当前标签子节点列表的指定位置插入对象(Tag或NavigableString)
```python
html = ‘<b><a href="http://example.com/">I linked to <i>example.com</i></a></b>‘
soup = BeautifulSoup(html)
tag = soup.a
tag.contents
tag.insert(1, "but did not endorse ")
tag.contents
  • insert_before() 和 insert_after() 方法则在当前标签之前或之后的兄弟节点添加元素

    
    html = ‘<b><a href="http://example.com/">I linked to <i>example.com</i></a></b>‘
    soup = BeautifulSoup(html)
    tag = soup.new_tag("i")
    tag.string = "Don‘t"
    soup.b.insert_before(tag)
    soup.b
* wrap() 和 unwrap()可以对指定的tag元素进行包装或解包,并返回包装后的结果。

```python
# 添加包装
soup = BeautifulSoup("<p>I wish I was bold.</p>")
soup.p.string.wrap(soup.new_tag("b"))
#输出 <b>I wish I was bold.</b>

soup.p.wrap(soup.new_tag("div"))
#输出 <div><p><b>I wish I was bold.</b></p></div>

# 拆解包装
markup = ‘<a href="http://example.com/">I linked to <i>example.com</i></a>‘
soup = BeautifulSoup(markup)
a_tag = soup.a

a_tag.i.unwrap()
a_tag
#输出 <a href="http://example.com/">I linked to example.com</a>

删除标签

html = ‘<b><a href="http://example.com/">I linked to <i>example.com</i></a></b>‘
soup = BeautifulSoup(html)
# 清楚当前标签的所有子节点
soup.b.clear()

# 将当前标签及所有子节点从soup 中移除,返回当前标签。
b_tag=soup.b.extract()
b_tag
soup

# 将当前标签及所有子节点从soup 中移除,无返回。
soup.b.decompose()

# 将当前标签替换为指定的元素
tag=soup.i
new_tag = soup.new_tag("p")
new_tag.string = "Don‘t"
tag.replace_with(new_tag)

其他方法

输出

# 格式化输出
tag.prettify()
tag.prettify("latin-1")
  • 使用Beautiful Soup解析后,文档都被转换成了Unicode,特殊字符也被转换为Unicode,如果将文档转换成字符串,Unicode编码会被编码成UTF-8.这样就无法正确显示HTML特殊字符了
  • 使用Unicode时,Beautiful Soup还会智能的把“引号”转换成HTML或XML中的特殊字符

文档编码

使用Beautiful Soup解析后,文档都被转换成了Unicode,其使用了“编码自动检测”子库来识别当前文档编码并转换成Unicode编码。

soup = BeautifulSoup(html)
soup.original_encoding

# 也可以手动指定文档的编码
soup = BeautifulSoup(html, from_encoding="iso-8859-8")
soup.original_encoding

# 为提高“编码自动检测”的检测效率,也可以预先排除一些编码
soup = BeautifulSoup(markup, exclude_encodings=["ISO-8859-7"])
  • 通过Beautiful Soup输出文档时,不管输入文档是什么编码方式,默认输出编码均为UTF-8编码

文档解析器

Beautiful Soup目前支持, “lxml”, “html5lib”, 和 “html.parser”

soup=BeautifulSoup("<a><b /></a>")
soup
#输出: <html><body><a><b></b></a></body></html>
soup=BeautifulSoup("<a></p>", "lxml")
soup
#输出: <html><body><a></a></body></html>
soup=BeautifulSoup("<a></p>", "html5lib")
soup
#输出: <html><head></head><body><a><p></p></a></body></html>
soup=BeautifulSoup("<a></p>", "html.parser")
soup
#输出: <a></a>

参考文档

https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh

原文地址:https://blog.51cto.com/13673090/2466801

时间: 2024-10-10 23:15:14

Python下利用BeautifulSoup解析HTML的相关文章

Python中利用xpath解析HTML

在进行网页抓取的时候,分析定位html节点是获取抓取信息的关键,目前我用的是lxml模块(用来分析XML文档结构的,当然也能分析html结构), 利用其lxml.html的xpath对html进行分析,获取抓取信息: 首先,我们需要安装一个支持xpath的python库.目前在libxml2的网站上被推荐的python binding是lxml,也有beautifulsoup,不嫌麻烦的话还可以自己用正则表达式去构建,本文以lxml为例讲解. 假设有如下的HTML文档 1 <html> 2 &

python爬虫之BeautifulSoup

Beautiful Soup,字面意思是美好的汤,是一个用于解析HTML文件的Python库 windows下载和安装 在Windows下面如何安装Beautiful Soup: 1.到http://www.crummy.com/software/BeautifulSoup/网站上上下载 2.下载完成之后需要解压缩,假设放到D:/python下. 3.运行cmd,切换到D:/python/beautifulsoup4-4.1.3/目录下(根据自己解压缩后的目录和下载的版本号修改), cd /d

Python 爬虫—— requests BeautifulSoup

本文记录下用来爬虫主要使用的两个库.第一个是requests,用这个库能很方便的下载网页,不用标准库里面各种urllib:第二个BeautifulSoup用来解析网页,不然自己用正则的话很烦. requests使用,1直接使用库内提供的get.post等函数,在比简单的情况下使用,2利用session,session能保存cookiees信息,方便的自定义request header,可以进行登陆操作. BeautifulSoup使用,先将requests得到的html生成BeautifulSo

python学习(25) BeautifulSoup介绍和实战

BeautifulSoup是python的html解析库,处理html非常方便 BeautifulSoup 安装 pip install beautifulsoup4 BeautifulSoup 配合的解析器 # python标准库 BeautifulSoup(html,'html.parser') #lxml HTML 解析器 BeautifulSoup(html,'lxml) #html5lib BeautifulSoup(html,'html5lib') python 标准库解析器不需要第

python ConfigParser模块 配置文件解析

ConfigParser模块主要是用来解析配置文件的模块,像mysql,或者win下面的ini文件等等 下面我们来解析mysql的配置文件my.cnf my.cnf配置文件内容 [mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock user=mysql # Disabling symbolic-links is recommended to prevent assorted security risks symbolic

(转)python下很帅气的爬虫包 - Beautiful Soup 示例

官方文档地址:http://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html Beautiful Soup 相比其他的html解析有个非常重要的优势.html会被拆解为对象处理.全篇转化为字典和数组. 相比正则解析的爬虫,省略了学习正则的高成本. 相比xpath爬虫的解析,同样节约学习时间成本.虽然xpath已经简单点了.(爬虫框架Scrapy就是使用xpath) 安装 linux下可以执行 [plain] view plai

python中的BeautifulSoup使用小结

1.安装 pip install beautifulsoup4 2.代码文件中导入 from bs4 import BeautifulSoup 3. 解析器 使用方法 优势 劣势 Python标准库 BeautifulSoup(markup, "html.parser") Python的内置标准库 执行速度适中 文档容错能力强 Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差 lxml HTML 解析器 BeautifulSoup(markup, "lx

Python实现XML文件解析

1. XML简介 XML(eXtensible Markup Language)指可扩展标记语言,被设计用来传输和存储数据,已经日趋成为当前许多新生技术的核心,在不同的领域都有着不同的应用.它是web发展到一定阶段的必然产物,既具有SGML的核心特征,又有着HTML的简单特性,还具有明确和结构良好等许多新的特性. test.XML文件 <?xml version="1.0" encoding="utf-8"?> <catalog> <m

Python之利用Whoosh搭建轻量级搜索

??本文将简单介绍Python中的一个轻量级搜索工具Whoosh,并给出相应的使用示例代码. Whoosh简介 ??Whoosh由Matt Chaput创建,它一开始是一个为Houdini 3D动画软件包的在线文档提供简单.快速的搜索服务工具,之后便慢慢成为一个成熟的搜索解决工具并已开源. ??Whoosh纯由Python编写而成,是一个灵活的,方便的,轻量级的搜索引擎工具,现在同时支持Python2.3,其优点如下: Whoosh纯由Python编写而成,但很快,只需要Python环境即可,不