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 非关系型数 ...
随机推荐
- Spring Boot + Spring Cloud 构建微服务系统(一):服务注册和发现(Consul)
使用Consul提供注册和发现服务 什么是 Consul Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置.与其它分布式服务注册与发现的方案,Consul ...
- iOS开发(0):框架QMUIKit的使用 | 使用第三方UI框架 | cocoapods的使用
对于移动APP来说,客户端(iOS或android)的界面开发是必不可少的工作.为了减轻界面开发的工作量,也为了提高开发的速度,选择一个良好的界面框架,是有意义的. iOS开源的界面框架有很多,比如c ...
- 深入理解苹果系统(Unicode)字符串的排序方法
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由iminder发表于云+社区专栏 Unicode编码 我们知道计算机是不能直接处理文本的,而是和数字打交道.因此,为了表示文本,就建立 ...
- 前端错误监控,sentry入门配置详细教程
一.前言 最近经理说要把公司项目结合sentry用起来,然后组长不想做,老员工也不想做,分配任务就这么分配给我了,很荣幸接锅,摸索了几天,了解了一些基本配置,深一点的玩法可能还得实践一段时间,这里对于 ...
- ReactNative常用组件汇总
导航组件react-navigation: https://github.com/react-community/react-navigation 网络请求asios: https://github. ...
- C#微信公众号开发--网页授权(oauth2.0)获取用户基本信息一
前言 微信网页授权共分为两种方式:snsapi_base.snsapi_userinfo. snsapi_base需要关注公众号,获取用户信息时不弹出用户授权界面. snsapi_userinfo是在 ...
- 菜鸟入门【ASP.NET Core】9:RoutingMiddleware介绍以及MVC引入
前言 前面介绍了使用app.Map来配置路由,但是对于一般不是特别大的项目来说,不使用Map来进行路由配置. 配置路由 我们首先需要在Startup.cs文件中的ConfigureServices方法 ...
- Redis Eval Script
简介 从Redis 2.6 版本开始,内嵌支持 Lua 环境.通过使用EVAL或EVALSHA命令可以使用 Lua 解释器来执行脚本. EVAL和EVALSHA的使用是差不多的(下面有讲区别). EV ...
- [PHP] 算法-二位有序数组中查找的PHP实现
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 1.二 ...
- JAVA对Excel的导入导出
今天需要对比2个excel表的内容找出相同:由于要学的还很多上手很慢所以在这做个分享希望对初学的有帮助: 先是pom的配置: <dependency> <groupId>org ...