[Python] - 爬虫之Beautiful Soup的基本使用
2017-12-24 16:36
621 查看
Beautiful Soup的简介
Beautiful Soup 是一个可以从HTML或
XML文件中提取数据的
Python库,最主要的功能是从网页抓取数据
官方解释如下:
Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。
Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。
Beautiful Soup已成为和lxml、html6lib一样出色的python解释器,为用户灵活地提供不同的解析策略或强劲的速度。
Beautiful Soup 安装
命令行安装
可以利用pip或者
easy_install来安装,以下两种方法均可
easy_install beautifulsoup4 # 或者 pip3 install beautifulsoup4
安装包安装
下载完成之后解压: Beautiful Soup 4.3.2运行下面的命令即可完成安装
sudo python setup.py install
安装解析器
Beautiful Soup支持
Python标准库中的
HTML解析器,还支持一些第三方的解析器,其中一个是 lxml
$ easy_install lxml 或 $ pip install lxml
基本使用
这里是官方文档链接,不过内容是有些多,也不够条理,在此选部分常用功能示例官方文档
BeautifulSoup 对象
将一段文档传入BeautifulSoup的构造方法,就能得到一个文档的对象, 可以传入一段字符串或一个文件句柄
from bs4 import BeautifulSoup # 打来一个 html 文件 soup = BeautifulSoup(open('index.html')) # 打来 html 格式字符串 soup = BeautifulSoup('<html>data</html>')
对象的种类
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:Tag
NavigableString
BeautifulSoup
Comment
Tag
Tag是什么?通俗点讲就是
HTML中的一个个标签
Tag对象与
XML或
HTML原生文档中的
tag相同
>>> soup = BeautifulSoup('<b class="boldest">Extremely</b>', "lxml") >>> tag = soup.b >>> tag <b class="boldest">Extremely</b> >>> type(tag) <class 'bs4.element.Tag'>
tag中最重要的属性:
Name: 每个
tag都有自己的名字,通过
.name来获取
Attributes:
tag的属性, 属性的操作方法与字典相同
name属性和获取和修改
# 获取 tag 的 name >>> tag.name 'b' # 修改 tag 的 name # 如果改变了tag的name,那将影响所有通过当前Beautiful Soup对象生成的HTML文档 >>> tag.name = "blcokquote" >>> tag <blcokquote class="boldest">Extremely</blcokquote>
Attributes属性的操作
一个
tag可能有很多个属性.
tag <b class="boldest">有一个
“class”的属性,值为
“boldest”
tag的属性的操作方法与字典相同
tag的属性可以被添加,删除或修改, 操作方法与字典一样
# 获取 tag 的 class 属性值,返回一个列表 >>> tag['class'] ['boldest'] >>> tag['class'][0] 'boldest' >>> tag.attrs {'class': ['boldest']} # 修改 tag 的 class 和 id 属性 >>> tag['class'] = 'mazy' >>> tag['id'] = 1 >>> tag <blcokquote class="mazy" id="1">Extremely</blcokquote> # 删除 tag 的 class 属性 >>> del tag['class'] >>> tag <blcokquote id="1">Extremely</blcokquote> # 删除 tag 的 id 属性 >>> del tag['id'] >>> tag <blcokquote>Extremely</blcokquote>
多值属性
HTML 定义了一系列可以包含多个值的属性,最常见的多值的属性是 class (一个tag可以有多个CSS的class).在Beautiful Soup中多值属性的返回类型是 List
>>> css_soup = BeautifulSoup('<p class="body strikeout"></p>','lxml') >>> css_soup.p['class'] ['body', 'strikeout']
在任何版本的
HTML定义中都没有被定义为多值属性,那么
Beautiful Soup会将这个属性作为字符串返回
>>> id_soup = BeautifulSoup('<p id="my id"></p>', 'lxml') >>> id_soup.p['id'] 'my id'
NavigableString
字符串常被包含在tag内.
Beautiful Soup用
NavigableString类来包装
tag中的字符串
tag中包含的字符串不能编辑,但是可以被替换成其它的字符串,用
replace_with()方法
>>> tag <blcokquote class="boldest">Extremely</blcokquote> >>> tag.string 'Extremely' >>> type(tag.string) <class 'bs4.element.NavigableString'> >>> tag.string.replace_with('No longer bold') >>> tag <blcokquote>No longer bold</blcokquote>
遍历文档树
操作示例代码: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> """
创建 BeautifulSoup
文档对象
>>> soup = BeautifulSoup(html_doc, 'html.parser') # soup 对象 >>> soup <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 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>
子节点
一个Tag可能包含多个字符串或其它的 Tag,这些都是这个 Tag 的子节点Tag
的名字
# 获取 head 标签 >>> soup.head <head><title>The Dormouse's story</title></head> # 获取 title 标签 >>> soup.title <title>The Dormouse's story</title> # 这是个获取tag的小窍门,可以在文档树的tag中多次调用这个方法.下面的代码可以获取<body>标签中的第一个<b>标签 >>> soup.body.b <b>The Dormouse's story</b> # 获取第一个 a 标签 >>> soup.a <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a> # 如果想要得到所有的<a>标签,或是通过名字得到比一个tag更多的内容的时候,就需要用到: find_all() >>> soup.find_all('a') [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
Tag
的 .contents
和 .children
属性
Tag的
.contents属性可以将
Tag的子节点以列表的方式输出
字符串没有
.contents属性,因为字符串没有子节点
# 获取 head 标签内部的内容 >>> soup.head.contents [<title>The Dormouse's story</title>] # 获取 head 标签内部的内容的第一个元素 >>> soup.head.contents[0] <title>The Dormouse's story</title> # 获取 head 标签内部的内容的第一个元素的内容 >>> soup.head.contents[0].contents ["The Dormouse's story"]
通过
Tag的
.children生成器,可以对
Tag的子节点进行循环
for child in soup.body.p.children: print(child) # <b>The Dormouse's story</b>
搜索文档树
Beautiful Soup定义了很多搜索方法,这里着重介绍2个:
find()
find_all()
使用 find_all() 类似的方法可以查找到想要查找的文档内容
字符串搜索
最简单的过滤器是字符串.在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容下面的例子用于查找文档中所有的标签
>>> soup.find_all('b') [<b>The Dormouse's story</b>]
正则表达式搜索
import re # 下面例子中找出所有以b开头的标签 for tag in soup.find_all(re.compile("^b")): print(tag.name) #body #b
参数列表搜索
如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回
下面代码找到文档中所有
<a>标签和
<b>标签:
>>> soup.find_all(['a','b']) [<b>The Dormouse's story</b>, <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
方法 / 函数搜索
如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 ,如果这个方法返回True表示当前元素匹配并且被找到,如果不是则反回
False
下面方法校验了当前元素,如果包含
class同时属性包含
id属性,那么将返回
True
def has_class_and_id(tag): return tag.has_attr('class') and tag.has_attr('id') # 将这个方法作为参数传入 find_all() 方法,将得到所有<a>标签: result = soup.find_all(has_class_and_id) print(result) # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
find() 的使用
find( name , attrs , recursive , string , **kwargs )
使用
find_all()方法并设置
limit=1参数不如直接使用
find()方法.
下面两行代码是等价的:
>>> soup.find_all('title', limit=1) [<title>The Dormouse's story</title>] # 等价于 >>> soup.find('title') <title>The Dormouse's story</title>
find_all()
和 find()
的区别:
唯一的区别是 find_all()方法的返回结果是值包含一个元素的列表,而
find()方法直接返回结果
find_all()方法没有找到目标是返回空列表,
find()方法找不到目标时,返回
None
CSS选择器
Beautiful Soup支持大部分的
CSS选择器, 在
Tag或
BeautifulSoup对象的
.select()方法中传入字符串参数, 即可使用CSS选择器的语法找到
Tag
>>> soup.select('title') [<title>The Dormouse's story</title>]
通过 tag
标签逐层查找
>>> soup.select('body a') [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>] >>> soup.select('html head title') [<title>The Dormouse's story</title>]
找到某个 tag
标签下的直接子标签
>>> soup.select('head > title') [<title>The Dormouse's story</title>] >>> soup.select('p > a') [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>] >>> soup.select('p > #link1') [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>] >>> soup.select('body > a') []
通过 CSS
的类名查找
>>> soup.select('.sister') [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
通过 tag
的 id
查找
>>> soup.select('#link1') [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>] >>> soup.select('a#link1') [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
同时用多种 CSS
选择器查询元素
>>> soup.select('#link1, #link2') [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
返回查找到的元素的第一个
>>> soup.select_one('.sister') <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
相关文章推荐
- 萌新的Python学习日记 - 爬虫无影 - 使用BeautifulSoup + urlretrieve 抓取并保存图片:weheartit
- 萌新的Python学习日记 - 爬虫无影 - 使用BeautifulSoup + css selector 抓取动态网页内容:Knewone
- 使用requests+beautifulsoup模块实现python网络爬虫功能
- 萌新的Python学习日记 - 爬虫无影 - 使用BeautifulSoup + css selector 抓取自己想要网页内容
- Python BeautifulSoup基本使用
- [转载]Python爬虫入门八之Beautiful Soup的用法
- Python爬虫利器二之Beautiful Soup的用法
- Python爬虫入门八之Beautiful Soup的用法
- 使用Python编写爬虫的基本模块及框架使用指南
- python3+BeautifulSoup+tkinter 爬虫 获取学校成绩
- Python爬虫利器二之Beautiful Soup的用法【转过来,乱了,从原网址看】
- Python爬虫利器二之Beautiful Soup的用法
- Python爬虫入门三之Urllib库的基本使用
- Python爬虫入门一之Urllib库的基本使用
- 转 Python爬虫入门三之Urllib库的基本使用
- Python爬虫入门八之Beautiful Soup的用法
- Python爬虫入门三之Urllib库的基本使用
- python 爬虫试手 requests+BeautifulSoup
- [转载]Python爬虫入门三之Urllib库的基本使用