Python3爬虫神器之BeautifulSoup(一)——初识
BeautifulSoup是一个可以从HTML和XML中提取数据的Python库,BeautifulSoup化平淡为神奇,通过定位HTML 标签来格式化和组织复杂的网络信息,有了它的帮助你会节省数个小时甚至数天的时间。BeautifulSoup并不是Python的标准库所以要额外安装。我们可以直接pip安装。安装完BeautifulSoup之后我们可以安装一下解析器当然也可以不安装。因为BeautifulSoup支持Python标准库中的HTML解析器,另外两个解析器分别是lxml和纯Python实的html5lib。你们可能会问既然python的标准库都有解析器为什么我们还要去安装额外的呢,自然每一个解析器都有自己的优缺点咯。以下是BeautifulSoup4.2.0文档给出的优缺点
python标准库 , 使用方法:BeautifulSoup(markup,"html.parser") ,优势: 1.python的内置标准库 2.执行速度适中 3.文档容错能力强 劣势: 1.python2.7.2or3.2.2前到的版 2.执行速度适中本文档容错能力弱
lxml HTML 解析器 ,使用方法: BeautifulSoup(markup,"lxml") 优势1.速度快 2.文档容错能力强 劣势:1.需要安装C语言库
lxml XML解析器 使用方法: BeautifulSoup(markup,["lxml","xml"]) 优势: 1.速度快 2.唯一支持XML的解析器 劣势 1.需要安装C语言库
html5lib 使用方法: BeautifulSoup(markup,"html5lib") 优势: 1.最好的的兼容性 2.以浏览器的方式解析文档 3.生成HTML5格式的文档 劣势: 1.速度慢 2.不依赖外部扩展
当然了如果你和我一样懒不想去安装那些扩展的
解析器其实问题也不是很大,Python标准库中的解析器能过满足我们绝大多数的需求
既然安装完了那么我们就要引用它
from bs4 import BeautifulSoup
讲一段文档传入BeautifulSoup的构造方法就能的到一个文档对象,可以传入一个字符串或者文件句柄文档里面给了一个例子。其中文档被转换成Unicode,并且HTML的实例都被转换成Unicode编码Beautiful Soup选择最合适的解析器来解析这段文档,如果手动指定解析器那么Beautiful Soup会选择指定的解析器来解析文档
soup = BeautifulSoup("<html>data</html>")
如果你在Windows上直接运行指端代码是会报错的(linus和Mac上没有试过),emmm,其实不能说是报错,那只是一个warning
warning的大概意思就是:没有确切的语法分析器被指定所以我为这个系统(lxml)使用最便利的HTML解析器这并不是一个问题,但是如果你在其他系统上使用这段代码或者在虚拟环境下使用这段代码那么她将会使用不同的解析器并且表现的不一样
为了祛除这个报错你可以将你的代码从 BeautifulSoup(YOUR_MARKUP})形式转换为BeautifulSoup(YOUR_MARKUP, "lxml")形式。
也就是说我们要将我们的代码改成这种形式
soup = BeautifulSoup("<html>data</html>","lxml")
这段代码的运行就没有问题
BeautifulSoup将复杂的HTML文档转换为一个复杂的树形结构,每个节点都是python的对象所有对象可以分为四种:Tag,NavigableString , BeautifulSoup , Comment
那么我们先分别来解释一下这四个对象是什么意思
Tag:BeautifulSoup 对象通过find 和findAll,或者直接调用子标签获取的一列对象或单个对象,就像bs.div.h1
NavigableString:用来表示标签里的文字,不是标签(有些函数可以操作和生成NavigableString 对象,而不是标签对象)。
BeautifulSoup:被BeautifulSoup解析过的对象
Comment:用来查找HTML 文档的注释标签
啥是树形结构呢,树形结构可以拿下面这张图理解一下嘛
此图来自《python网络数据采集》我们先来讲讲Tag,这个对象和XML以及HTML原生文档中的tag相同,tag中最重要的属性:name和attributes
name:每一个tag都有自己的名字也就是HTML中标签的名字例如
soup = BeautifulSoup('<b class= "sadfasdf">adfgas</b>','lxml')
tag = soup.b
那么其中b就是这个tag的name我们可以用.name来获取tag的name例如
tag.name
attributes:一个tag可以有多个attributes。如上一例中有一个class的attributes的值为sadfasdf,tag的attributes的操纵方法和字典相同例:tag['class'] 这可以得出结果sadfasdf。也可以直接用‘.’来取值比如:.attrs
例:tag.attrs。可以得出结果:{'class': ['sadfasdf']}。tag的attributes可以修改,其操纵方法也和字典一样
HTML4中定义了一系列可以包含多个值的attributes,HTML5中移除了一些但是增加了更多。其中最常见的多值属性就是class ,一个tag可以有多个class,还有一些attributes: rel , rev , accept-charset , headers , accesskey。记住在BeautifulSoup中多值返回类型是list
见以下例子:
cs = BeautifulSoup('<p class="sdf sadf"></p>')
cs.p["class"]
我们可以的到结果['sdf', 'sadf']
如果某个attributes看起来好像有多个值,但没有被定义为多值属性,那么Beautiful Soup会将这个attributes作为字符串返回
见一下例子:
idb = BeautifulSoup('<p id = "my id"></p>')
idb.p['id']
那么我们将会的到'my id'的结果
将tag转换为字符串的时候多值属性将会转换为一个值,还有如果转的文档格式是xml那么就不包含多值
字符串常常包含在tag内也就是<b class = "sdfsadf">pretty good</b>中的pretty good。BeautifulSoup中用NavigableString类型包装tag的字符串
soup = BeautifulSoup('<b class = "sdfsadf">pretty good</b>')
tag = soup.b
tag.string
可以得出pretty good
再查看一下它的类型
tag中包含的字符串不能编辑,但是可以被替换成其它的字符串,用 replace_with() 方法:
>>>tag.string.replace_with("No away")
>>>tag
可以得到结果<b class="sdfsadf">No away</b>
顺便也说说replace_with()这个方法,replace_with()这个方法用来一处文档树中的某段内容并用新的tag或者文本节点代替它。用法:PageElement.replace_with()并会返回被替代的tag或文本节点,可以用来浏览或添加到文档树其它地方
再来简单的提一下BeautifulSoup对象
BeautifulSoup对象表示的是一个文档的全部内容,大部分时候可以将它作为tag对象,它支持遍历文档树和搜索文档树中的绝大多数方法。但是BeautifulSoup对象并不是真正的HTML和XML的tag所以没有name和attributes,但是它有一个值为“[document]”的特殊属性.name
Comment对象是一个特殊的NavigableString对象,但是在HTML文档中时会以特殊格式输出