Python3编写网络爬虫06-基本解析库Beautiful Soup的使用
二、Beautiful Soup
简介 就是python的一个HTML或XML的解析库 可以用它来很方便的从网页中提取数据
0.1 提供一些简单的 python式的函数来处理导航,搜索,修改分析树等功能,
它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用
0.2 自动将输入的文档转换为Unicode编码,输出文档转换为UTF-8编码,不需要考虑编码方式,
除非文档没有指定一个编码方式,这是你仅仅需要说明以下原始编码格式就可以了。
0.3 已成为和lxml,html6lib一样出色的python解释器,为用户灵活地提供不同的解析策略或强劲的速度。
安装 Beautiful Soup 解析器依赖lxml库 保证lxml库安装
pip install beautifulsoup4
验证:
from bs4 import BeautifulSoup
soup = BeautifulSoup('<p>Hello</p>','lxml')
print(soup.p.string) #输出Hello
1.解析器
BeautifulSoup在解析的时候 依赖解析器 除了支持python标准库HTML解析器之外 还支持第三方解析器(lxml)
例如
解析器 优势 劣势
python标准库 python内置标准库 执行速度适中, python2.7.3及python3.2.2之前的版本 文档容错率差
文档容错能力强
lxml HTML解析器 速度快 文档容错能力强 需要安装C语言库
lxml XML解析器 速度快 唯一支持XML的解析器 需要安装C语言库
html5lib 最好的容错性,以浏览器的方式解析文档 速度慢 不依赖外部拓展
生成HTML5格式文档
对比可以看出lxml解析器有解析HTML和XML的功能 速度快 容错能力强
使用时 将第二个参数改为lxml
2.基本用法
html='''
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dormouse"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their name 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(soup.prettify())#把要解析的字符串以标准的缩进格式输出
print(soup.title.string)#输出HTML中title节点的文本内容
3.节点选择器
直接调用节点的名字就可以选择节点元素,再调用string属性就可以得到节点内的文本,
这种选择方式速度非常快,如果单个节点结构层次清晰可以选用这种方式
3.1 选择元素
html='''
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dormouse"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their name 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(soup.title)#获取title节点 print(type(soup.title))#打印类型为bs4.element.Tag类型 经过选择器选择后 结果都是这种Tag类型 print(soup.title.string)#调用Tag里的string属性 得到节点的文本内容 print(soup.head)#查找heda节点 print(soup.p)#查找p节点 结果只有一个 后面的没有选到 这种方式只会选择到第一个匹配的节点
3.2 提取信息
获取节点名称
可以利用name属性获取节点名称 选取title节点 调用name属性
print(soup.title.name)
获取属性
每个节点可能有多个属性 比如 id class ... 选择这个节点元素后,可以调用attrs获取所有属性
print(soup.p.attrs)#返回结果是字典形式
# 获取字典里面某个键值 只需要中括号加属性名
print(soup.p.attrs['name'])
更简单的获取方式
print(soup.p['name'])#返回结果是字符串
print(soup.p['class'])#返回结果是列表 实际处理时要注意类型
3.3获取内容
print(soup.p.string)#返回结果是第一个p节点的文本内容
3.4 嵌套选择
html='''
<html><head><title>The Dormouse's story</title></head>
<body>
'''
from bs4 import BeautifulSoup soup = BeautifulSoup(html,'lxml')
print(soup.head.title)#title节点元素
print(type(soup.head.title))#打印类型为Tag 在Tag基础上再次选择得到的依然是Tag
print(soup.head.title.string)#输出string属性 获取文本内容
3.5关联选择
子节点和子孙节点
html='''
<html>
<head>
<title>The Dormouse's story</title>
</head>
<body>
<p class="story">
Once upon a time there were three litile sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">
<span>Elsie</span>
</a>
<a href="http://example/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,'lxml')
print(soup.p.contents)
结果是列表形式 p节点里包含文本 又包含节点
注意:列表中的每个元素都是p节点的直接子节点 例如span 相当于p节点的子孙节点 但是结果没有单独选出来
contents 返回直接子节点的列表
也可以使用children属性
print(soup.p.children)#返回结果是迭代器 for i,child in enumerate(soup.p.children):
print(i,child)#遍历
descendants 子孙节点
print(soup.p.descendants)#返回结果是生成器 for i,child in enumerate(soup.p.descendants):
print(i,child)#遍历 得到所有子孙节点
父节点和祖先节点
获取某个节点的父节点 可以调用parent属性
print(soup.a.parent)#返回p节点及其内部内容 获取某个节点的祖先节点 可以调用parents属性 print(soup.a.parents)#返回生成器 print(list(enumerate(soup.a.parents)))#列表输出索引和内容 列表中的元素就是a标签的祖先节点
兄弟节点
html = '''
<html>
<body>
<p class="story">
Once
<a href="www.baidu.com">
<span>Elsie</span>
</a>
Hello
<a href="www.baidu2.com">Lacie</a>
and
<a href="www.baidu3.com">Tillie</a>
and they
</p>
'''
soup = BeautifulSoup(html,'lxml') print('Next Sibling',soup.a.next_sibling)#获取节点的下一个兄弟元素
print('Prev Sibling',soup.a.previous_sibling)#获取节点的上一个兄弟元素
print('Next Siblings',list(enumerate(soup.a.next_siblings)))#获取后面的兄弟节点
print('Prev Siblings',list(enumerate(soup.a.previous_siblings)))#获取前面的兄弟节点
提取信息
示例:
html='''
<html>
<body>
<p class="story">
Once upon...; and their
<a href="www.baidu.com" class="sister" id="link1">Bod</a><a href="www.baidu2.com"
class="sister" id="link2">Lacie</a>
</p>
''' soup = BeautifulSoup(html,'lxml') print('Next Sibling:')
print(type(soup.a.next_sibling))
print(soup.a.next_sibling)
print(soup.a.next_sibling.string)
print('Parent:')
print(type(soup.a.parents))
print(list(soup.a.parents)[0])
print(list(soup.a.parents)[0].attrs['class'])
如果返回的是单个节点,可以直接调用string attrs等属性获取文本和属性
如果返回的是多个节点,可以转为列表后取出某个元素再调用string attrs获取对应节点的文本和属性
4.方法选择器
find_all() #查询所有符合条件的元素
find_all(name,attrs,recursive,text,**kwargs)
4.1 name #根据节点名查询元素
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>
''' soup = BeautifulSoup(html,'lxml') print(soup.find_all(name="ul"))#查找所有ul节点
print(type(soup.find_all(name="ul")[0]))#类型为Tag类型
查询其内部的li节点
for ul in soup.find_all(name="ul"):
print(ul.find_all(name="li"))
遍历每个li 获取文本内容
for ul in soup.find_all(name="ul"):
print(ul.find_all(name="li"))
for li in ul.find_all(name="li"):
print(li.string)
4.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>
'''
soup = BeautifulSoup(html,'lxml') print(soup.find_all(attrs={'id':'list-1'}))#结果为列表形式
print(soup.find_all(attrs={'name':'elements'}))
简写方式
print(soup.find_all(id="list-1"))#返回id 为list-1的节点元素
print(soup.find_all(class_="element"))#由于class在python中是关键字 所以加 _ 结果依然是Tag类型的列表
4.3 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>
''' soup = BeautifulSoup(html,'lxml') print(soup.find_all(text=re.compile('link')))#返回正则表达式匹配的节点文本 组成的列表
4.4 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" id="list-2">
<li class="element">Foo</li>
<li class="element">Bar</li>
</ul>
</div>
</div>
''' soup = BeautifulSoup(html,'lxml') print(soup.find(name="ul"))
print(type(soup.find(name="ul")))
print(soup.find(class_="list"))
# 返回结果不再是列表形式 只有第一个匹配元素 类型依然是Tag类型
更多查询方法 用法相同 范围不同
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() :前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点
5.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" 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>
''' soup = BeautifulSoup(html,'lxml') print(soup.select('.panel .panel-heading'))
print(soup.select('ul li'))
print(soup.select('#list-2 .element'))
print(type(soup.select('ul')[0]))#类型依然是Tag类型
5.1 嵌套选择
示例:
soup = BeautifulSoup(html,'lxml')
for ul in soup.select('ul'):
print(ul.select('li'))#返回ul下 所有li组成的列表
5.2 获取属性
示例:获取所有ul节点的id属性
for ul in soup.select('ul'):
print(ul['id'])
print(ul.attrs['id'])
5.3 获取文本
可以选择用string 或者 get_text()
for li in soup.select('li'):
print('Get Text:',li.get_text())
print('String',li.string)
#效果完全相同
总结: 推荐使用lxml解析库 必要时使用html.parser
节点选择筛选功能弱但是速度快
建议使用 find() 或者 find_all() 查询匹配单个结果或者多个结果
如果对CSS选择器熟悉 可以使用 select() 方法选择
Python3编写网络爬虫06-基本解析库Beautiful Soup的使用的更多相关文章
- Python3编写网络爬虫05-基本解析库XPath的使用
一.XPath 全称 XML Path Language 是一门在XML文档中 查找信息的语言 最初是用来搜寻XML文档的 但是它同样适用于HTML文档的搜索 XPath 的选择功能十分强大,它提供了 ...
- Python3编写网络爬虫07-基本解析库pyquery的使用
三.pyquery 简介:同样是一个强大的网页解析工具 它提供了和jQuery类似的语法来解析HTML文档,支持CSS选择器,使用非常方便 安装: pip install pyquery 验证: im ...
- Python3编写网络爬虫02-基本请求库requests的使用
一.requests 库使用 需要安装 pip install requests import requests #导入requests库 request = requests.get("h ...
- Python3编写网络爬虫01-基本请求库urllib的使用
安装python后 自带urllib库 模块篇 分为几个模块如下: 1. urllib.request 请求模块 2. urllib.parse 分析模块 3. urllib.error 异常处理模块 ...
- 小白学 Python 爬虫(21):解析库 Beautiful Soup(上)
小白学 Python 爬虫(21):解析库 Beautiful Soup(上) 人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前 ...
- 小白学 Python 爬虫(22):解析库 Beautiful Soup(下)
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- python3编写网络爬虫20-pyspider框架的使用
二.pyspider框架的使用 简介 pyspider是由国人binux 编写的强大的网络爬虫系统 github地址 : https://github.com/binux/pyspider 官方文档 ...
- python3编写网络爬虫21-scrapy框架的使用
一.scrapy框架的使用 前面我们讲了pyspider 它可以快速的完成爬虫的编写 不过pyspider也有一些缺点 例如可配置化不高 异常处理能力有限对于一些反爬虫程度非常强的网站 爬取显得力不从 ...
- Python3编写网络爬虫08-数据存储方式一-文件存储
数据存储 用解析器解析出数据之后,就是存储数据了.保存的形式可以多种多样,最简单的形式是直接保存为文本文件,如TXT JSON CSV等.另外还可以保存到数据库中,如关系型数据库MySQL 非关系型数 ...
随机推荐
- (转)深度学习目标检测指标mAP
深度学习目标检测指标mAP https://github.com/rafaelpadilla/Object-Detection-Metrics 参考上面github链接中的readme,有详细描述
- thinkphp如何利用反射实现钩子方法
ThinkPHP框架的控制器模块是如何实现 前控制器.后控制器,及如何执行带参数的方法? PHP系统自带的 ReflectionClass.ReflectionMethod 类,可以反射用户自定义类的 ...
- 设计模式之备忘录模式(Memento )
当我们在实际应用中需要提供撤销机制,当一个对象可能需要再后续操作中恢复其内部状态时,就需要使用备忘录模式.其本质就是对象的序列化和反序列化的过程,支持回滚操作. 作用 在不破坏封装性的前提下,捕获一个 ...
- 微信公共号:CTO技术总监
业务价值胜过技术策略: 战略目标胜过具体项目的效益: 内置的互操作胜过定制的集成: 共享服务胜过特定目标的实现: 灵活性胜过优化: 不断演进地提炼胜过在最开始追求完美!
- php中一个字符占用几个字节?
先看看字符与字节有什么区别: (一)“字节”的定义 字节(Byte)是一种计量单位,表示数据量多少,它是计算机信息技术用于计量存储容量的一种计量单位. (二)“字符”的定义 字符是指计算机中使用的文字 ...
- MAC MYSQ忘记密码重置方法
网友的方法,记个笔记请勿转载. step1: 关闭mysql服务: 苹果->系统偏好设置->最下边点mysql 在弹出页面中 关闭mysql服务(点击stop mysql server) ...
- 初学CSS-4-文字颜色属性
{ color : red ; color : rgb(255,0,0); (红,绿,蓝)值越大,越亮 color : rgba(255,0,0,1); 第四位数字:透明度(0~1),值越小越透明 ...
- 随机生成n个不重复的数,范围是2-32,并让其在新页面打开
var n = 5 var timer; function suiji(){ var arr = [] // 循环生成n个随机数 for(var i=0;i<n;i++){ var num = ...
- The server quit without updating PID file (data mysql.pid)
(1)mysql的安装路径和运行路径 # whereis mysqld (2)PATH变量指定的路径中,搜索mysql的信息 # which mysqld (3)查看配置文件 # ...
- 2014年GDG西安 -- DevFest Season1
今年9月21日,GDG西安组织了第一季以Android Wear为专题的活动,葡萄城则以超一流的办公环境和网络宣传,配合举行了本次活动.下面通过图文方式进行报道,希望未能如期参加的筒子们不要有太多的遗 ...