python之Beautiful Soup的基本用法
Posted 夏日的向日葵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python之Beautiful Soup的基本用法相关的知识,希望对你有一定的参考价值。
Beautiful Soup就是Python的一个HTML或XML的解析库,可以用它来方便地从网页中提取数据。它有如下三个特点:
- Beautiful Soup提供一些简单的、Python式的函数来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。
- Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为UTF-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时你仅仅需要说明一下原始编码方式就可以了。
- Beautiful Soup已成为和lxml、html6lib一样出色的Python解释器,为用户灵活地提供不同的解析策略或强劲的速度。
首先,我们要安装它:pip install bs4,然后安装 pip install beautifulsoup4.
一、Beautiful Soup支持的解析器
下面我们以lxml解析器为例:
from bs4 import BeautifulSoup soup = BeautifulSoup(\'<p>Hello</p>\', \'lxml\') print(soup.p.string)
结果:
Hello
beautiful soup美化的效果实例:
html = """ <html><head><title>The Dormouse\'s story</title></head> <body> <p class="title" name="dromouse"><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> """ from bs4 import BeautifulSoup soup = BeautifulSoup(html, \'lxml\')
#调用prettify()方法。这个方法可以把要解析的字符串以标准的缩进格式输出 print(soup.prettify()) print(soup.title.string)
结果:
<html> <head> <title> The Dormouse\'s story </title> </head> <body> <p class="title" name="dromouse"> <b> The Dormouse\'s story </b> </p> <p class="story"> Once upon a time there were three little sisters; and their names were <a class="sister" href="http://example.com/elsie" id="link1"> <!-- Elsie --> </a> , <a class="sister" href="http://example.com/lacie" id="link2"> Lacie </a> and <a class="sister" href="http://example.com/tillie" id="link3"> Tillie </a> ; and they lived at the bottom of a well. </p> <p class="story"> ... </p> </body> </html> The Dormouse\'s story
二、下面举例说明选择元素、属性、名称的方法
html = """
<html><head><title>The Dormouse\'s story</title></head>
<body>
<p class="title" name="dromouse"><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>
"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, \'lxml\')
print(\'输出结果为title节点加里面的文字内容:\\n\',soup.title)
print(\'输出它的类型:\\n\',type(soup.title))
print(\'输出节点的文本内容:\\n\',soup.title.string)
print(\'结果是节点加其内部的所有内容:\\n\',soup.head)
print(\'结果是第一个p节点的内容:\\n\',soup.p)
print(\'利用name属性获取节点的名称:\\n\',soup.title.name)
#这里需要注意的是,有的返回结果是字符串,有的返回结果是字符串组成的列表。
# 比如,name属性的值是唯一的,返回的结果就是单个字符串。
# 而对于class,一个节点元素可能有多个class,所以返回的是列表。
print(\'每个节点可能有多个属性,比如id和class等:\\n\',soup.p.attrs)
print(\'选择这个节点元素后,可以调用attrs获取所有属性:\\n\',soup.p.attrs[\'name\'])
print(\'获取p标签的name属性值:\\n\',soup.p[\'name\'])
print(\'获取p标签的class属性值:\\n\',soup.p[\'class\'])
print(\'获取第一个p节点的文本:\\n\',soup.p.string)
结果:
输出结果为title节点加里面的文字内容:
<title>The Dormouse\'s story</title>
输出它的类型:
<class \'bs4.element.Tag\'>
输出节点的文本内容:
The Dormouse\'s story
结果是节点加其内部的所有内容:
<head><title>The Dormouse\'s story</title></head>
结果是第一个p节点的内容:
<p class="title" name="dromouse"><b>The Dormouse\'s story</b></p>
利用name属性获取节点的名称:
title
每个节点可能有多个属性,比如id和class等:
{\'class\': [\'title\'], \'name\': \'dromouse\'}
选择这个节点元素后,可以调用attrs获取所有属性:
dromouse
获取p标签的name属性值:
dromouse
获取p标签的class属性值:
[\'title\']
获取第一个p节点的文本:
The Dormouse\'s story
在上面的例子中,我们知道每一个返回结果都是bs4.element.Tag类型,它同样可以继续调用节点进行下一步的选择。
html = """ <html><head><title>The Dormouse\'s story</title></head> <body> """ from bs4 import BeautifulSoup soup = BeautifulSoup(html, \'lxml\') print(\'获取了head节点元素,继续调用head来选取其内部的head节点元素:\\n\',soup.head.title) print(\'继续调用输出类型:\\n\',type(soup.head.title)) print(\'继续调用输出内容:\\n\',soup.head.title.string)
结果:
获取了head节点元素,继续调用head来选取其内部的head节点元素: <title>The Dormouse\'s story</title> 继续调用输出类型: <class \'bs4.element.Tag\'> 继续调用输出内容: The Dormouse\'s story
三、方法选择器
(1)find_all()
find_all,顾名思义,就是查询所有符合条件的元素。给它传入一些属性或文本,就可以得到符合条件的元素,它的功能十分强大。
find_all(name , attrs , recursive , text , **kwargs)
他的用法:
html=\'\'\' <div class="panel"> <div class="panel-heading"> <h4>Hello</h4> </div> <div class="panel-body"> <ul class="list" id="list-1"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul> <ul class="list list-small" id="list-2"> <li class="element">Foo</li> <li class="element">Bar</li> </ul> </div> </div> \'\'\' from bs4 import BeautifulSoup soup = BeautifulSoup(html, \'lxml\') print(\'查询所有ul节点,返回结果是列表类型,长度为2:\\n\',soup.find_all(name=\'ul\')) print(\'每个元素依然都是bs4.element.Tag类型:\\n\',type(soup.find_all(name=\'ul\')[0])) #将以上步骤换一种方式,遍历出来 for ul in soup.find_all(name=\'ul\'): print(\'输出每个u1:\',ul.find_all(name=\'li\')) #遍历两层 for ul in soup.find_all(name=\'ul\'): print(\'输出每个u1:\',ul.find_all(name=\'li\')) for li in ul.find_all(name=\'li\'): print(\'输出每个元素:\',li.string)
结果:
查询所有ul节点,返回结果是列表类型,长度为2: [<ul class="list" id="list-1"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul>, <ul class="list list-small" id="list-2"> <li class="element">Foo</li> <li class="element">Bar</li> </ul>] 每个元素依然都是bs4.element.Tag类型: <class \'bs4.element.Tag\'> 输出每个u1: [<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>] 输出每个u1: [<li class="element">Foo</li>, <li class="element">Bar</li>] 输出每个u1: [<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>] 输出每个元素: Foo 输出每个元素: Bar 输出每个元素: Jay 输出每个u1: [<li class="element">Foo</li>, <li class="element">Bar</li>] 输出每个元素: Foo 输出每个元素: Bar
(2) attrs()
除了根据节点名查询,我们也可以传入一些属性来查询,示例如下:
html=\'\'\' <div class="panel"> <div class="panel-heading"> <h4>Hello</h4> </div> <div class="panel-body"> <ul class="list" id="list-1" name="elements"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul> <ul class="list list-small" id="list-2"> <li class="element">Foo</li> <li class="element">Bar</li> </ul> </div> </div> \'\'\' from bs4 import BeautifulSoup soup = BeautifulSoup(html, \'lxml\') print(\'返回符合id为list-1的所有节点:\\n\',soup.find_all(attrs={\'id\': \'list-1\'})) print(\'返回符合name为elements的所有节点:\\n\',soup.find_all(attrs={\'name\': \'elements\'})) #对于一些常用的属性,比如id和class等,我们可以不用attrs来传递 print(\'返回符合id为list-1的所有节点(简单版):\\n\',soup.find_all(id=\'list-1\')) #而对于class来说,由于class在Python里是一个关键字,所以后面需要加一个下划线 print(\'返回符合name为elements的所有节点(简单版):\\n\',soup.find_all(class_=\'element\'))
结果:
返回符合id为list-1的所有节点: [<ul class="list" id="list-1" name="elements"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul>] 返回符合name为elements的所有节点: [<ul class="list" id="list-1" name="elements"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul>] 返回符合id为list-1的所有节点(简单版): [<ul class="list" id="list-1" name="elements"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul>] 返回符合name为elements的所有节点(简单版): [<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>, <li class="element">Foo</li>, <li class="element">Bar</li>]
(3) text
text参数可用来匹配节点的文本,传入的形式可以是字符串,可以是正则表达式对象,示例如下:
import re html=\'\'\' <div class="panel"> <div class="panel-body"> <a>Hello, this is a link</a> <a>Hello, this is a link, too</a> </div> </div> \'\'\' from bs4 import BeautifulSoup soup = BeautifulSoup(html, \'lxml\') #这里在find_all()方法中传入text参数,该参数为正则表达式对象 # 结果返回所有匹配正则表达式的节点文本组成的列表。 print(\'含link列表:\\n\',soup.find_all(text=re.compile(\'link\')))
结果:
列表: [\'Hello, this is a link\', \'Hello, this is a link, too\']
(4) find()
除了find_all()方法,还有find()方法,只不过后者返回的是单个元素,也就是第一个匹配的元素,而前者返回的是所有匹配的元素组成的列表。示例如下:
html=\'\'\' <div class="panel"> <div class="panel-heading"> <h4>Hello</h4> </div> <div class="panel-body"> <ul class="list" id="list-1"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul> <ul class="list list-small" id="list-2"> <li class="element">Foo</li> <li class="element">Bar</li> </ul> </div> </div> \'\'\' from bs4 import BeautifulSoup soup = BeautifulSoup(html, \'lxml\') print(\'返回第一个匹配的节点元素:\\n\',soup.find(name=\'ul\')) print(\'返回第一个匹配的节点元素类型:\\n\',type(soup.find(name=\'ul\'))) print(\'返回第一个匹配的节点元素:\\n\',soup.find(class_=\'list\'))
结果:
返回第一个匹配的节点元素: <ul class="list" id="list-1"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul> 返回第一个匹配的节点元素类型: <class \'bs4.element.Tag\'> 返回第一个匹配的节点元素: <ul class="list" id="list-1"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul>
四、CSS选择器
Beautiful Soup还提供了另外一种选择器,那就是CSS选择器。使用CSS选择器时,只需要调用select()方法,传入相应的CSS选择器即可,示例如下:
html=\'\'\' <div class="panel"> <div class="panel-heading"> <h4>Hello</h4> </div> <div class="panel-body"> <ul class="list" id="list-1"> <li class="element">Foo</li> <li class="element">Bar</li> <li class="element">Jay</li> </ul> <ul class="list list-small" id="list-2"> <li class="element">Foo</li> <li class="element">Bar</li> </ul> </div> </div> \'\'\' from bs4 import BeautifulSoup soup = BeautifulSoup(html, \'lxml\') print(\'选择panel下的panel-heading标签:\\n\',soup.select(\'.panel .panel-heading\')) print(\'选择ul下的li标签:\\n\',soup.select(\'ul li\')) print(\'选择list-2下的element标签:\\n\',soup.select(\'#list-2 .element\')) print(\'返回第一个u1的类型:\\n\',type(soup.select(\'ul\')[0])) #嵌套选择 for ul in soup.select(\'ul\'): print(\'打印每个u1下的li标签:\\n\',ul.select(\'li\')) #尝试获取每个ul节点的id属性: for ul in soup.select(\'ul\'): print(\'打印每个u1下的id的内容:\\n\',ul[\'id\']) print(\'打印每个u1下的id的内容(另一种方法):\\n\',ul.attrs[\'id\']) #获取文本 for li in soup.select(\'li\'): print(\'获取li的文本信息:\', li.get_text()) print(\'获取li的文本信息(另一种方法):\', li.string)
结果:
选择panel下的panel-heading标签: [<div class="panel-heading"> <h4>Hello</h4> </div>] 选择ul下的li标签: [<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>, <li class="element">Foo</li>, <li class="element">Bar</li>] 选择list-2下的element标签: [<li class="element">Foo</li>, <li class="element">Bar</li>] 返回第一个u1的类型: <class \'bs4.element.Tag\'> 打印每个u1下的li标签: [<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>] 打印每个u1下的li标签: [<li class="element">Foo</li>, <li class="element">Bar</li>] 打印每个u1下的id的内容: list-1 打印每个u1下的id的内容(另一种方法): list-1 打印每个u1下的id的内容: list-2 打印每个u1下的id的内容(另一种方法): list-2 获取li的文本信息: Foo 获取li的文本信息(另一种方法): Foo 获取li的文本信息: Bar 获取li的文本信息(另一种方法): Bar 获取li的文本信息: Jay 获取li的文本信息(另一种方法): Jay 获取li的文本信息: Foo 获取li的文本信息(另一种方法): Foo 获取li的文本信息: Bar 获取li的文本信息(另一种方法): Bar
到此,Beautiful Soup的用法基本就介绍完了,最后做一下简单的总结。
推荐使用lxml解析库,必要时使用html.parser。
节点选择筛选功能弱但是速度快。
建议使用find()或者find_all()查询匹配单个结果或者多个结果。
如果对CSS选择器熟悉的话,可以使用select()方法选择。
原文链接:https://blog.csdn.net/qq_35490191/article/details/80598620
以上是关于python之Beautiful Soup的基本用法的主要内容,如果未能解决你的问题,请参考以下文章
python爬虫之Beautiful Soup库,基本使用以及提取页面信息
python爬虫之Beautiful Soup库,基本使用以及提取页面信息