>>> from env_helper import info; info()
页面更新时间: 2024-01-17 15:01:14
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-17-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

5.5. Web页面解析

HTML 文档本身是结构化的文本,有一定的规则,通过它的结构可以简化信息提取。 于是,就有了lxml、pyquery、BeautifulSoup等网页信息提取库。 一般我们会用这些库来提取网页信息。 其中,lxml 有很高的解析效率,支持 xPath 语法(一种可以在 HTML 中查找信息的规则语法); pyquery 得名于 jQuery(知名的前端 js 库),可以用类似 jQuery 的语法解析网页。 BeautifulSoup4同样是使用频率较高,处理效果比较理想的库。

BeautifulSoup4是一个HTML/XML的解析器,主要的功能是解析和提取HTML/XML的数据。和lxml库一样。

lxml只会局部遍历,而BeautifulSoup4是基于HTML DOM的,会加载整个文档,解析整个DOM树,因此内存开销比较大,性能比较低。

BeautifulSoup4用来解析HTML比较简单,API使用非常人性化,支持CSS选择器,是Python标准库中的HTML解析器,也支持lxml解析器。

BeautifulSoup4主要的解析器,以及它们的优缺点:

  • Python标准库

    • 优点:Python的内置标准库,执行速度适中,文档容错能力强

    • 缺点:中文档容错能力差

  • lxml HTML 解析器

    • 优点:速度快文档容错能力强

    • 缺点:使用步骤繁琐,需要安装C语言库

  • lxml XML 解析器

    • 优点:速度快唯一支持XML的解析器

    • 缺点:使用步骤繁琐,需要安装C语言库

  • html5lib

    • 优点:最好的容错性以浏览器的方式解析文档生成HTML5格式的文档

    • 缺点:速度慢不依赖外部扩展

5.5.1. 安装

使用pip进行安装:

pip install beautifulsoup4

在 Debina/ Ubuntu 系统中安装:

sudo apt install -y python3-bs4

5.5.2. 测试

以 IGADC 网站为例,通过 requests 库请求 html 页面的内容。并引入BeautifulSoup库来查看html页面的相关信息。

>>> import requests
>>> from bs4 import BeautifulSoup
>>> url='http://www.igadc.cn/'
>>> headers = {
>>>             'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36'
>>>           }
>>> html = requests.get(url, headers=headers, timeout=10000)
>>> demo = html.text

查看 HTML 页面头部信息:

>>> soup = BeautifulSoup(demo,"html.parser")
>>> soup.head
<head>
<meta charset="utf-8"/>
<meta content="www.igadc.cn" name="generator"/>
<meta content="pc,mobile" name="applicable-device"/>
<meta content="www.igadc.cn" name="author"/>
<meta content="www.igadc.cn" name="Copyright"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<link href="/static/favicon.ico" mce_href="/static/favicon.ico" rel="icon" type="image/x-icon"/>
<link href="/static/favicon.ico" mce_href="/static/favicon.ico" rel="shortcut icon" type="image/x-icon"/>
<script src="/static/f2elib/jquery/jquery-3.3.1.min.js?v=f8da8f95b6ed33542a88af19028e18ae3d9ce25350a06bfc3fbf433ed2b38fefa5e639cddfdac703fc6caa7f3313d974b92a3168276b3a016ceb28f27db0714a"></script>
<script src="/static/f2elib/bootstrap_3.3.7/js/bootstrap.min.js?v=8b3b64a1bb2f9e329f02d4cd7479065630184ebaed942ee61a9ff9e1ce34c28c0eecb854458977815cf3704a8697fa8a5d096d2761f032b74b70d51da3e37f45"></script>
<script src="/static/f2elib/jquery-validate_1.15.0/jquery.validate.min.js?v=0da5e2cd6eeb9de26233f5ce9d341543bc0364154d5dfe54f6b13cf013d8850704438a63684665097e61818dfee02dcaf758df7695166f3f2df262ff8350434f"></script>
<script src="/static/f2elib/magnific-popup_1.1.0/jquery.magnific-popup.min.js?v=22c361e44dde632dedaff2625f6631e2fb02ba3b6487097b48baa09f02cd81fd381ebb7d053f525e52e56655b1f8e2b89ddcc0a002e1b0c35c0a6920823641d7"></script>
<script src="/static/f2elib/leaflet_1.3.1/leaflet.js?v=b6280d0b767f2747258718b2ffb31b5ee1091b6a7e49aec9b8abff25ad6d232b9fee4e360f5802688ed43a446cc6a80f0fef45b23ed3af793fe1d8a817a12c15"></script>
<script src="/static/f2elib/leaflet/leaflet.ChineseTmsProviders.js?v=24f734210bd9277f01e24be313d4d087fd4c5831489bca8fe96e6e70a6b5169969f7d2273cfc3c317bc3660dfde5ee85847d091b39ea0a952f621e4b528eb09b"></script>
<link href="/static/f2elib/bootstrap_3.3.7/css/bootstrap.min.css?v=e8c5daf01eae68ed7c1e277a6e544c7ad108a0fa877fb531d6d9f2210769b7da88e4e002c7b0be3b72154ebf7cbf01a795c8342ce2dad368bd6351e956195f8b" rel="stylesheet"/>
<link href="/static/f2elib/leaflet_1.3.1/leaflet.css?v=464b26e517a70442922858e02376b8d6fae3930e0454f949dfe3a223ae6f4e321da3d6eb94069c12e28e890e4e161edc388d5b903c0ba9d2f0dd983471124001" rel="stylesheet"/>
<script src="/static/f2elib/codemirror_5.25.0/lib/codemirror.js?v=3fedfaf4a6d6eb6befdc2a12da3d8c1b1f1ed48b461bbcd679e38251cb5e7f43e1dd117b752e83ccd6868805fcbb95c62d75cc7d3487fd980010174aef6ec996"></script>
<script src="/static/f2elib/codemirror_5.25.0/addon/edit/continuelist.js?v=2a1989cdc974ed376b701488182bc3b3ab49a6b87d300b051e7198fdebebe52f80eedb1d6428c7a97e1aa24a4fd0c86221f9ba6cbe3881d4e64643080d18cf22"></script>
<script src="/static/f2elib/codemirror_5.25.0/mode/markdown/markdown.js?v=762a1979a2cca8b868398f3671a4a466a08a68c6f9c690f40a8f814893a33a727a997415daefd2bed712ff7acd5b5b8c14e2a7f61b267c4e5fcf16b1750517db"></script>
<link href="/static/f2elib/codemirror_5.25.0/lib/codemirror.css?v=76e8d7d110f1a96f56511993745fb61ae1f59018f5c25bb0b8a65cd82362126ac5a1d13b2a07e95f18b5c536d9fc50b4adef9b284340229a30d6647d7732c934" rel="stylesheet"/>
<link href="/static/tass/css/style.css?v=aa9ec3b99a531d9a2bdf519dfc27ae63dfc5c37eb268a47d17d0090801763c76436092353271900fc475fdfc6d96ba53f7e05900ec44b5e0c3f57d4abc31a10f" rel="stylesheet" type="text/css"/>
<link href="/static/css/dropdown.css?v=d8e3d047fc6695a8b41765eda5c5bc471a196d10e3c25b45d0e8aaca1c6822ceb8cffedce508abdb79b4c7c1b658536d29bb528961f9a26fdc7e4a21af02baf5" rel="stylesheet" type="text/css"/>
<title>东北亚资源环境大数据中心</title>
<meta content="东北亚资源环境大数据中心" name="keywords"/>
<meta content="东北亚资源环境大数据中心" name="description"/>
<script type="text/javascript">
$().ready(function () {
$("#find_calc").validate(
{
rules: {
keyword: {
required: true
}
},
messages: {
keyword: {
required: "<span class='red'>Please enter the key words to query</span>"
}
}
}
);
});
</script>
<style type="text/css">
#map_div {
width: 100%;
height: 420px;
border: 1px solid black;
text-align: center;
align-self: center;
z-index: 1;
}
</style>
<link href="/static/css/nav-hidden.css" rel="stylesheet"/>
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?fc17a7c3f593f2612726ce8d229021f6";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</head>

查看 HTML 页面头部内容中带有“contents” 属性的标签:

>>> soup.head.contents[:10]
['n',
 <meta charset="utf-8"/>,
 'n',
 <meta content="www.igadc.cn" name="generator"/>,
 'n',
 <meta content="pc,mobile" name="applicable-device"/>,
 'n',
 <meta content="www.igadc.cn" name="author"/>,
 'n',
 <meta content="www.igadc.cn" name="Copyright"/>]

查看html页面中图片信息:

>>> soup.img
<img class="img-thumbnail" src="/static/tass/images/findata1.png" style="width: 10%"/>

查看 HTML 页面的标题:

>>> soup.title
<title>东北亚资源环境大数据中心</title>

5.5.3. 遍历文档树

我们得到的 HTML 信息详单与一个树的组织,他由多个节点组成,子节点、子孙节点。

子节点和获取字符串

一个Tag可能包含多个字符串或其它的Tag , 这些都是这个Tag的子节点。 Beautiful Soup提供了许多操作和遍历子节点的属性。

下面的代码可以获取<body>标签中的第一个<b>标签:

>>> soup.body.b
<b class="caret"></b>

如果想要得到所有的 <a> 标签,或是通过名字得到比一个tag更多的内容的时候, 就需要用到 Searching the tree 中描述的方法,比如: find_all() ,这能获取所有的 <a> 标签:

>>> soup.find_all('a')[:5]
[<a class="navbar-brand" href="/">IGADC</a>,
 <a href="/special/list?tag=agroecology" title="数据目录">数据目录</a>,
 <a href="/sci-lab/index.html" title="科学计算">科学计算</a>,
 <a href="/post/" title="文档">文档</a>,
 <a href="/science/index.html" title="教育科普">教育科普</a>]

contents 属性返回所有子节点的列表,包括 NavigableString 类型节点。如果节点当中有换行符,会被当做是 NavigableString 类型节点而作为一个子节点:

>>> soup.head.contents[:5]
['n',
 <meta charset="utf-8"/>,
 'n',
 <meta content="www.igadc.cn" name="generator"/>,
 'n']

如果 tag 只有一个 NavigableString 类型子节点,那么这个 tag 可以使用 .string 获取子节点。 如果一个 tag 仅有一个子节点,那么这个 tag 也可以使用 .string 方法,输出结果与当前唯一子节点的 .string 结果相同。 如果 tag 包含了多个子节点,tag 就无法确定 .string 方法应该调用哪个子节点的内容, .string 的输出结果是 None

.string 获取子节点:

>>> soup_1 = BeautifulSoup("""<div>
>>>     <p><span><b>test</b></span></p>
>>> </div>
>>> """)
>>> soup_1.p.string
'test'

5.5.4. 查找

最简单的过滤器是字符串.在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容,下面的例子用于查找文档中所有的<b>标签:

>>> soup.find_all('b')
[<b class="caret"></b>, <b>电子邮件</b>]

如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,这表示<body><b>标签都应该被找到:

>>> import re
>>> for tag in soup.find_all(re.compile("^b")):
>>>     print(tag.name)
body
button
b
br
br
br
b

如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有<a>标签和<b>标签:

>>> soup.find_all(["title", "b"])
[<title>东北亚资源环境大数据中心</title>, <b class="caret"></b>, <b>电子邮件</b>]

True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点

>>> for tag in soup.find_all(True)[:5]:
>>>     print(tag.name)
html
head
meta
meta
meta

find_all()

find_all() 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件.

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

>>> soup.find_all("link")
[<link href="/static/favicon.ico" mce_href="/static/favicon.ico" rel="icon" type="image/x-icon"/>,
 <link href="/static/favicon.ico" mce_href="/static/favicon.ico" rel="shortcut icon" type="image/x-icon"/>,
 <link href="/static/f2elib/bootstrap_3.3.7/css/bootstrap.min.css?v=e8c5daf01eae68ed7c1e277a6e544c7ad108a0fa877fb531d6d9f2210769b7da88e4e002c7b0be3b72154ebf7cbf01a795c8342ce2dad368bd6351e956195f8b" rel="stylesheet"/>,
 <link href="/static/f2elib/leaflet_1.3.1/leaflet.css?v=464b26e517a70442922858e02376b8d6fae3930e0454f949dfe3a223ae6f4e321da3d6eb94069c12e28e890e4e161edc388d5b903c0ba9d2f0dd983471124001" rel="stylesheet"/>,
 <link href="/static/f2elib/codemirror_5.25.0/lib/codemirror.css?v=76e8d7d110f1a96f56511993745fb61ae1f59018f5c25bb0b8a65cd82362126ac5a1d13b2a07e95f18b5c536d9fc50b4adef9b284340229a30d6647d7732c934" rel="stylesheet"/>,
 <link href="/static/tass/css/style.css?v=aa9ec3b99a531d9a2bdf519dfc27ae63dfc5c37eb268a47d17d0090801763c76436092353271900fc475fdfc6d96ba53f7e05900ec44b5e0c3f57d4abc31a10f" rel="stylesheet" type="text/css"/>,
 <link href="/static/css/dropdown.css?v=d8e3d047fc6695a8b41765eda5c5bc471a196d10e3c25b45d0e8aaca1c6822ceb8cffedce508abdb79b4c7c1b658536d29bb528961f9a26fdc7e4a21af02baf5" rel="stylesheet" type="text/css"/>,
 <link href="/static/css/nav-hidden.css" rel="stylesheet"/>]

name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉.

>>> soup.find_all("title")
[<title>东北亚资源环境大数据中心</title>]

keyword 参数如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,.

>>> soup.find_all(href=re.compile("//www.osgeo.cn"))[:5]
[<a href="http://www.osgeo.cn/" target="_blank" title="OSGeo中国中心">OSGeo中国中心</a>]

按照CSS类名搜索tag的功能非常实用,但标识CSS类名的关键字 class 在Python中是保留字,使用 class 做参数会导致语法错误.从Beautiful Soup的4.1.1版本开始,可以通过 class_ 参数搜索有指定CSS类名的tag:

>>> soup.find_all( class_="badge")[:5]
[<span class="badge" style="float: right">
 2020-12-19
 </span>,
 <span class="badge" style="float: right">
 2020-12-19
 </span>,
 <span class="badge" style="float: right">
 2020-12-19
 </span>,
 <span class="badge" style="float: right">
 2020-12-19
 </span>,
 <span class="badge" style="float: right">
 2020-12-19
 </span>]

通过 text 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, text 参数接受 字符串 , 正则表达式 , 列表, True .

>>> soup.find_all(string="地图")
['地图']
>>> soup.find_all(string=re.compile("黑龙江"))
['nn黑龙江省地貌矢量数据nn',
 'n黑龙江省多年平均气温数据n',
 'n黑龙江省多年平均相对湿度数据n',
 'n黑龙江省1:50万盐碱地分布数据集(2000年)n',
 'n黑龙江省1:100万植被分布数据集(2000年)n',
 ' n<script>nfunction uv(result) {n$.each(result, function (i, field) {n//alert(i);nif (i == 'code') {n// window.location.href = '/page/' + field;n}nelse if (i == "uid") {n$("#wiki_edit_link").html('<a href="/page/_edit/' + field + '">Edit</a>');n}nelse if (i == "title") {n$("#wiki_title").html(field);n}nelse if (i == 'time_update') {nvar date = new Date(field * 1000);n$("#wiki_time_update").html(date.getFullYear() + '-' + date.getMonth() + '-' + date.getDay());n}nelse {n$("#wiki_cnt_html" ).html(field);n}n});n}nfunction load_post(post_id) {n$.getJSON("/post_j/" + post_id, function (result) {nuv(result);n})n}n</script>nnnn<li class="list-group-item" style="overflow: hidden; text-overflow:ellipsis; white-space: nowrap; display: block; ">n<span class="date">n2023-07-05</span>nn<span class="glyphicon glyphicon-list-alt"></span>nn<a href="/post/1158d" title="海伦示范区“东生”大豆入选黑龙江省主推品种">n海伦示范区“东生”大豆入选黑龙江省主推品种n</a>n</li>nnnnnn<li class="list-group-item" style="overflow: hidden; text-overflow:ellipsis; white-space: nowrap; display: block; ">n<span class="date">n2022-11-18</span>nn<span class="glyphicon glyphicon-list-alt"></span>nn<a href="/post/1f7b0" title="辽宁省1990生态系统空间分布数据">n辽宁省1990生态系统空间分布数据n</a>n</li>nnnnnn<li class="list-group-item" style="overflow: hidden; text-overflow:ellipsis; white-space: nowrap; display: block; ">n<span class="date">n2022-09-08</span>nn<span class="glyphicon glyphicon-list-alt"></span>nn<a href="/post/14fed" title="东北亚地理中心-吉林省">n东北亚地理中心-吉林省n</a>n</li>nnnnnn<li class="list-group-item" style="overflow: hidden; text-overflow:ellipsis; white-space: nowrap; display: block; ">n<span class="date">n2022-07-26</span>nn<span class="glyphicon glyphicon-list-alt"></span>nn<a href="/post/1476f" title="东北地理所科学数据中心顺利通过验收并被评为优秀">n东北地理所科学数据中心顺利通过验收并被评为优秀n</a>n</li>nnnnnn<li class="list-group-item" style="overflow: hidden; text-overflow:ellipsis; white-space: nowrap; display: block; ">n<span class="date">n2022-01-20</span>nn<span class="glyphicon glyphicon-list-alt"></span>nn<a href="/post/gi120" title="地学资讯速读——2022年1月20日">n地学资讯速读——2022年1月20日n</a>n</li>nnnnnn<li class="list-group-item" style="overflow: hidden; text-overflow:ellipsis; white-space: nowrap; display: block; ">n<span class="date">n2022-01-14</span>nn<span class="glyphicon glyphicon-list-alt"></span>nn<a href="/post/gi114" title="地学资讯速读——2022年1月14日">n地学资讯速读——2022年1月14日n</a>n</li>nnnnnn<li class="list-group-item" style="overflow: hidden; text-overflow:ellipsis; white-space: nowrap; display: block; ">n<span class="date">n2022-01-07</span>nn<span class="glyphicon glyphicon-list-alt"></span>nn<a href="/post/gi107" title="地学资讯速读——2022年1月7日">n地学资讯速读——2022年1月7日n</a>n</li>nnnnnn<li class="list-group-item" style="overflow: hidden; text-overflow:ellipsis; white-space: nowrap; display: block; ">n<span class="date">n2021-12-31</span>nn<span class="glyphicon glyphicon-list-alt"></span>nn<a href="/post/gic31" title="地学资讯速读——2021年12月31日">n地学资讯速读——2021年12月31日n</a>n</li>nnnnnn<li class="list-group-item" style="overflow: hidden; text-overflow:ellipsis; white-space: nowrap; display: block; ">n<span class="date">n2021-12-03</span>nn<span class="glyphicon glyphicon-list-alt"></span>nn<a href="/post/1f7de" title="白城市政府领导来所对接“黑土粮仓”科技会战大安示范区工作">n白城市政府领导来所对接“黑土粮仓”科技会战大安示范区工作n</a>n</li>nnnnnn<li class="list-group-item" style="overflow: hidden; text-overflow:ellipsis; white-space: nowrap; display: block; ">n<span class="date">n2021-09-24</span>nn<span class="glyphicon glyphicon-list-alt"></span>nn<a href="/post/gi924" title="地学资讯速读——2021年9月24日">n地学资讯速读——2021年9月24日n</a>n</li>nnnn']

limit 参数是find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢.如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量.效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果.

>>> len(soup.find_all("a"))
125
>>> soup.find_all("a", limit=5)
[<a class="navbar-brand" href="/">IGADC</a>,
 <a href="/special/list?tag=agroecology" title="数据目录">数据目录</a>,
 <a href="/sci-lab/index.html" title="科学计算">科学计算</a>,
 <a href="/post/" title="文档">文档</a>,
 <a href="/science/index.html" title="教育科普">教育科普</a>]

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

>>> soup.find_all("title")
[<title>东北亚资源环境大数据中心</title>]
>>> soup.html.find_all("title", recursive=False)
[]

find()

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

find_all() 方法将返回文档中符合条件的所有tag,尽管有时候我们只想得到一个结果.比如文档中只有一个<body>标签,那么使用 find_all() 方法来查找 <body> 标签就不太合适, 使用 find_all() 方法并设置 limit=1 参数不如直接使用 find() 方法.唯一的区别是 find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回结果.

find_all() 方法没有找到目标是返回空列表, find() 方法找不到目标时,返回 None .

>>> print(soup.find("aaaaaaa"))
None
>>> print(soup.find_all("aaaaaaa"))
[]

find_parents()find_parent()

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

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

我们已经用了很大篇幅来介绍 find_all()find() 方法,Beautiful Soup中还有10个用于搜索的API.它们中的五个用的是与 find_all() 相同的搜索参数,另外5个与 find() 方法的搜索参数类似.区别仅是它们搜索文档的不同部分.

注意: find_all()find() 只搜索当前节点的所有子节点,孙子节点等. find_parents()find_parent() 用来搜索当前节点的父辈节点,搜索方法与普通tag的搜索方法相同,搜索文档搜索文档包含的内容. 我们从一个文档中的一个叶子节点开始:

>>> a_string = soup.find(string="地图")
>>> a_string
'地图'
>>> a_string.find_parents("a")
[<a href="/map/" title="地图">地图</a>]

find_next_siblings()find_next_sibling()

find_next_siblings(name, attrs, recursive, text, **kwargs ) 方法返回所有符合条件的后面的兄弟节点

>>> first_link = soup.a
>>> first2_link = first_link.find_next_siblings(string=True)
>>> first2_link
['n']

find_next_sibling( name , attrs , recursive , text , **kwargs ) 只返回符合条件的后面的第一个tag节点.

>>> first3_link = first_link.find_next_sibling(string=True)
>>> first3_link
'n'

find_all_next()find_next()

find_all_next( name , attrs , recursive , text , **kwargs ) 返回所有符合条件的节点

>>> first_link.find_all_next(string=True)[:10]
['IGADC',
 'n',
 'n',
 'n',
 'n',
 ' <li class="dropdown hidden-mid">',
 'n',
 ' <a href="#" class="dropdown-toggle" data-toggle="dropdown">',
 'n',
 ' 学科分中心 <b class="caret"></b>']

find_next( name , attrs , recursive , text , **kwargs ) 返回第一个符合条件的节点

>>> first_link.find_next("p")
<p align="center" style="margin-top: 20px;color:#878B91;">Copyright © 中国科学院东北地理与农业生态研究所 <a href="https://beian.miit.gov.cn" target="_blank">吉ICP备05002032号</a></p>

5.5.5. 基于bs4库HTML的格式化输出

prettify() 方法将Beautiful Soup的文档树格式化后以Unicode编码输出,每个XML/HTML标签都独占一行

取出html页面头部内容进行prettify()方法处理

>>> soup.head.prettify()
'<head>n <meta charset="utf-8"/>n <meta content="www.igadc.cn" name="generator"/>n <meta content="pc,mobile" name="applicable-device"/>n <meta content="www.igadc.cn" name="author"/>n <meta content="www.igadc.cn" name="Copyright"/>n <meta content="width=device-width, initial-scale=1.0" name="viewport"/>n <link href="/static/favicon.ico" mce_href="/static/favicon.ico" rel="icon" type="image/x-icon"/>n <link href="/static/favicon.ico" mce_href="/static/favicon.ico" rel="shortcut icon" type="image/x-icon"/>n <script src="/static/f2elib/jquery/jquery-3.3.1.min.js?v=f8da8f95b6ed33542a88af19028e18ae3d9ce25350a06bfc3fbf433ed2b38fefa5e639cddfdac703fc6caa7f3313d974b92a3168276b3a016ceb28f27db0714a">n </script>n <script src="/static/f2elib/bootstrap_3.3.7/js/bootstrap.min.js?v=8b3b64a1bb2f9e329f02d4cd7479065630184ebaed942ee61a9ff9e1ce34c28c0eecb854458977815cf3704a8697fa8a5d096d2761f032b74b70d51da3e37f45">n </script>n <script src="/static/f2elib/jquery-validate_1.15.0/jquery.validate.min.js?v=0da5e2cd6eeb9de26233f5ce9d341543bc0364154d5dfe54f6b13cf013d8850704438a63684665097e61818dfee02dcaf758df7695166f3f2df262ff8350434f">n </script>n <script src="/static/f2elib/magnific-popup_1.1.0/jquery.magnific-popup.min.js?v=22c361e44dde632dedaff2625f6631e2fb02ba3b6487097b48baa09f02cd81fd381ebb7d053f525e52e56655b1f8e2b89ddcc0a002e1b0c35c0a6920823641d7">n </script>n <script src="/static/f2elib/leaflet_1.3.1/leaflet.js?v=b6280d0b767f2747258718b2ffb31b5ee1091b6a7e49aec9b8abff25ad6d232b9fee4e360f5802688ed43a446cc6a80f0fef45b23ed3af793fe1d8a817a12c15">n </script>n <script src="/static/f2elib/leaflet/leaflet.ChineseTmsProviders.js?v=24f734210bd9277f01e24be313d4d087fd4c5831489bca8fe96e6e70a6b5169969f7d2273cfc3c317bc3660dfde5ee85847d091b39ea0a952f621e4b528eb09b">n </script>n <link href="/static/f2elib/bootstrap_3.3.7/css/bootstrap.min.css?v=e8c5daf01eae68ed7c1e277a6e544c7ad108a0fa877fb531d6d9f2210769b7da88e4e002c7b0be3b72154ebf7cbf01a795c8342ce2dad368bd6351e956195f8b" rel="stylesheet"/>n <link href="/static/f2elib/leaflet_1.3.1/leaflet.css?v=464b26e517a70442922858e02376b8d6fae3930e0454f949dfe3a223ae6f4e321da3d6eb94069c12e28e890e4e161edc388d5b903c0ba9d2f0dd983471124001" rel="stylesheet"/>n <script src="/static/f2elib/codemirror_5.25.0/lib/codemirror.js?v=3fedfaf4a6d6eb6befdc2a12da3d8c1b1f1ed48b461bbcd679e38251cb5e7f43e1dd117b752e83ccd6868805fcbb95c62d75cc7d3487fd980010174aef6ec996">n </script>n <script src="/static/f2elib/codemirror_5.25.0/addon/edit/continuelist.js?v=2a1989cdc974ed376b701488182bc3b3ab49a6b87d300b051e7198fdebebe52f80eedb1d6428c7a97e1aa24a4fd0c86221f9ba6cbe3881d4e64643080d18cf22">n </script>n <script src="/static/f2elib/codemirror_5.25.0/mode/markdown/markdown.js?v=762a1979a2cca8b868398f3671a4a466a08a68c6f9c690f40a8f814893a33a727a997415daefd2bed712ff7acd5b5b8c14e2a7f61b267c4e5fcf16b1750517db">n </script>n <link href="/static/f2elib/codemirror_5.25.0/lib/codemirror.css?v=76e8d7d110f1a96f56511993745fb61ae1f59018f5c25bb0b8a65cd82362126ac5a1d13b2a07e95f18b5c536d9fc50b4adef9b284340229a30d6647d7732c934" rel="stylesheet"/>n <link href="/static/tass/css/style.css?v=aa9ec3b99a531d9a2bdf519dfc27ae63dfc5c37eb268a47d17d0090801763c76436092353271900fc475fdfc6d96ba53f7e05900ec44b5e0c3f57d4abc31a10f" rel="stylesheet" type="text/css"/>n <link href="/static/css/dropdown.css?v=d8e3d047fc6695a8b41765eda5c5bc471a196d10e3c25b45d0e8aaca1c6822ceb8cffedce508abdb79b4c7c1b658536d29bb528961f9a26fdc7e4a21af02baf5" rel="stylesheet" type="text/css"/>n <title>n  东北亚资源环境大数据中心n </title>n <meta content="东北亚资源环境大数据中心" name="keywords"/>n <meta content="东北亚资源环境大数据中心" name="description"/>n <script type="text/javascript">n  $().ready(function () {n$("#find_calc").validate(n{nrules: {nkeyword: {nrequired: truen}n},nmessages: {nkeyword: {nrequired: "<span class='red'>Please enter the key words to query</span>"n}n}n}n);n});n </script>n <style type="text/css">n  #map_div {nwidth: 100%;nheight: 420px;nborder: 1px solid black;ntext-align: center;nalign-self: center;nz-index: 1;n}n </style>n <link href="/static/css/nav-hidden.css" rel="stylesheet"/>n <script>n  var _hmt = _hmt || [];n(function() {nvar hm = document.createElement("script");nhm.src = "https://hm.baidu.com/hm.js?fc17a7c3f593f2612726ce8d229021f6";nvar s = document.getElementsByTagName("script")[0];ns.parentNode.insertBefore(hm, s);n})();n </script>n</head>n'

取出html页面头部内容中title标签进行prettify()方法处理

>>> soup.head.title.prettify()
'<title>n 东北亚资源环境大数据中心n</title>n'

Beautiful Soup输出是会将HTML中的特殊字符转换成Unicode,比如“&lquot;”:

>>> soup_3 = BeautifulSoup("&ldquo;Dammit!&rdquo; he said.")
>>> soup_3
<html><body><p>“Dammit!” he said.</p></body></html>

如果只想得到tag中包含的文本内容,那么可以调用 get_text() 方法,这个方法获取到tag中包含的所有文版内容包括子孙tag中的内容,并将结果作为Unicode字符串返回:

>>> soup.head.get_text()
'nnnnnnnnnnnnnnnnnnnnnnn东北亚资源环境大数据中心nnnnnnn'

任何HTML或XML文档都有自己的编码方式,比如ASCII 或 UTF-8 。但是使用Beautiful Soup解析后,文档都被转换成了Unicode 。 编码自动检测 功能大部分时候都能猜对编码格式,但有时候也会出错。 有时候即使猜测正确,也是在逐个字节的遍历整个文档后才猜对的,这样很慢。 如果预先知道文档编码,可以设置编码参数来减少自动检查编码出错的概率并且提高文档解析速度。 在创建 BeautifulSoup 对象的时候设置 from_encoding 参数。

>>> markup = b"<h1>\xed\xe5\xec\xf9</h1>"
>>> soup_3 = BeautifulSoup(markup)
>>> soup_3.original_encoding
'ISO-8859-7'