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 非关系型数 ...
随机推荐
- 第一篇:SpringBoot2.0简单介绍
距离Spring Boot1.0发布已经4年了,今年3月份SpringBoot2.0正式发布.让我们一起来了解一下它. Spring Boot主要依赖于Spring,整合了很多框架的使用方式,帮助开发 ...
- Debug技巧
多线程调试 有些时候为了观察多个线程间变量的不同状态,以及锁的获取等,就会想到在代码里加个断点debug一下. 在IDE里断点停下来的时候,可以切换到另外的线程中,跑其他的代码,不会互相影响.这里是有 ...
- centos6.10搭建ELK之elasticsearch6.5.4
1.环境准备 1.1.安装java环境版本不要低于java8 # java -version java version "1.8.0_191" Java(TM) SE Runtim ...
- nodejs+nginx获取真实ip
nodejs + nginx获取真实ip分为两部分: 第一.配置nginx: 第二.通过nodejs代码获取: 其他语言也是一样的,都是配置nginx之后,在http头里面获取“x-forwarded ...
- log | logstash
log | logstash log logstash enter description here 1. 安装 1. 安装java java -version 检查java版本 没有安装则到or ...
- python学习笔记02--列表和元组
一.简介 数据结构是通过某种方式组织在一起的数据元素的集合. 序列是python中最基本的数据结构,python中包含6种内建的序列,分别是列表.元组.字符串.Unicode字符串.buffer对象和 ...
- Java 多态 ——一个案例 彻底搞懂它
最近,发现基础真的hin重要.比如,Java中多态的特性,在学习中就是很难懂,比较抽象的概念.学的时候就犯糊涂,但日后会发现,基础在日常工作的理解中占有重要的角色. 下面,我将用一个代码实例,回忆和巩 ...
- vue VNode如何使用,是什么东西?
前言:element ui 中有些 demo 使用了 vue 的 VNode,但是 demo 毕竟不全,所以想要了解 VNode 到底是什么,如何写出符合自己业务的代码. vue 官网介绍:渲染函数 ...
- session一致性架构设计
什么是session? 由于HTTP协议是无状态的协议,因此它不会去记住上一次浏览器访问服务器时的信息.同一个用户的两次操作,与两个不同用户的操作,对它来说是一样的. 这样虽然满足了互联网web应用的 ...
- JS 判断是否是手机端并跳转操作
JS 判断运行当前脚本的应用程序是否为手机端或者一些其他信息,在我的工作中遇到的不是十分频繁,被我的同事一问就给问住了,所以把之前找到的一些知识点整理出来,供大家参考,若哪里不对欢迎指出,我会及时的更 ...