快速开始使用BeautifulSoup

首先创建一个我们需要解析的html文档,这里采用官方文档里面的内容:

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>
"""

要解析这段代码,需要导入BeautifullSoup,可以选择按照标准的缩进格式来输出内容:

from bs4 import BeautifulSoup#导入BeautifulSoup的方法
#可以传入一段字符串,或者传入一个文件句柄。一般都会先用requests库获取网页内容,然后使用soup解析。
soup=BeautifulSoup(html_doc,'html.parser')#这里一定要指定解析器,可以使用默认的html,也可以使用lxml比较快。
print(soup.prettify())#按照标准的缩进格式输出获取的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>

#几种简单浏览结构化数据的方法:
print(soup.title)#获取文档的title
print(soup.title.name)#获取title的name属性
print(soup.title.string)#获取title的内容
print(soup.title.parent.name)#获取title的parent名称,也就是head,上一级.
print(soup.p)#获取文档中第一个p节点
print(soup.p['class'])#获取第一个p节点的class内容
print(soup.a)#获取文档的第一个a节点
print(soup.find_all('a'))#获取文档中所有的a节点,返回一个list
soup.find(id='link3')#获取文档中id属性为link3的节点
<title>The Dormouse's story</title>
title
The Dormouse's story
head
<p class="title"><b>The Dormouse's story</b></p>
['title']
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</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>] <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
for link in soup.find_all('a'):
print(link.get('href'))#获取a节点的href属性
http://example.com/elsie
http://example.com/lacie
http://example.com/tillie
#print(soup.get_text())
print(soup.text)#两种方式都可以返回获取的所有文本
The Dormouse's story

The Dormouse's story
Once upon a time there were three little sisters; and their names were
Elsie,
Lacie and
Tillie;
and they lived at the bottom of a well.
...

对象的种类

其实HTML文档包含了很多的节点,这些节点一般可以归纳为4类,Tag,NavigableString,BeautifulSoup,Comment。

Tag

Tag就是html文档中的一个个标签。

主要介绍Tag的name和attributes属性。

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>','html.parser')
tag = soup.b
type(tag)
bs4.element.Tag
#Name
#属性通过.name来获取
#如果改变tag的name,那么所有当前BS对象的HTML文档都会改变。
print(tag.name)
tag.name='blockquote'
print(tag)
b
<blockquote class="boldest">Extremely bold</blockquote>
#Attributes
#获取方法比较简单,直接使用tag['attr_name']即可
#或者直接tag.attrs,可以返回所有的属性组成的字典。
print(tag['class'])
print(tag.attrs)
#tag的属性可以被删除或者修改,添加,与字典的操作方式一样
tag['class']='verybold'
tag['id']=1
print(tag)
#删除Tag的属性使用del方法
del tag['id']
verybold
{'id': 1, 'class': 'verybold'}
<blockquote class="verybold" id="1">Extremely bold</blockquote>
#有时候一个属性可能存在多个值,比如class,那么就会返回一个list
css_soup = BeautifulSoup('<p class="body strikeout"></p>','html.parser')
print(css_soup.p['class'])
['body', 'strikeout']
#将tag转换成字符串时,多值属性会合并为一个值;
rel_soup = BeautifulSoup('<p>Back to the <a rel="index">homepage</a></p>','html.parser')
rel_soup.a['rel'] = ['index', 'contents']
print(rel_soup.p)
#xml格式的文档不包含多值属性。
<p>Back to the <a rel="index contents">homepage</a></p>

NavigableString

可以遍历的字符串。

字符串通常被包含在tag内,BS用NavigableString类来包装tag中的字符串。

print(type(tag.string))#也就是tag的字符内容,<>string<>
<class 'bs4.element.NavigableString'>
#tag中的字符串不能编辑,但是可以替换成其他字符串
tag.string.replace_with('No longer bold')
print(tag)
<blockquote class="verybold">No longer bold</blockquote>

遍历文档数

还拿之前的html_doc来举例,演示如何从一段内容找到另一段内容。

soup=BeautifulSoup(html_doc,'html.parser')

子节点

一个tag可能包含多个字符串或者其他tag,都是这个tag的子节点。

#如果想要获取当前名字的第一个tag,直接用.tag_name就可以实现
print(soup.a)
#如果想要获取当前名字的所有tag,需要用find_all('tag_name')才可以
print(soup.find_all('a'))
#tag的.contents属性可以将tag的子节点以-列表-的方式输出
head_tag=soup.head
print(head_tag.contents)
#通过tag的.children生成器,可以对tag的子节点进行循环,(直接子节点)
for child in head_tag.children:
print(child)
#.descendants属性可以对所有tag的子孙节点进行递归循环:
for child in head_tag.descendants:
print(child)
#.string属性,如果tag只有一个NavigableString类型子节点,那么这个tag可以使用.string得到子节点:
#如果包含多个子节点,tag就无法确定.string的方法应该调用哪个子节点,所以输出None。 #如果tag中包含多个字符串,可以用.strings来循环获取,输出的字符串可能包含多个空格或空行,
#使用.stripped_strings可以去除多余空白内容。
for string in soup.stripped_strings:
print(repr(string))

父节点

每个tag或字符串都由父节点,也就是包含在某个tag中。

#.parent属性,用于获取某个元素的父节点,比如:
title_tag=soup.title
print(title_tag.parent)
#文档title的字符串也有父节点,title标签
#.parents,可以遍历tag到根节点的所有节点。
<head><title>The Dormouse's story</title></head>

兄弟节点

一段文档以标准格式输出时,兄弟节点有相同的缩进级别.

.next_sibling和.previous_sibling属性,用来查询兄弟节点:

.next_siblings和.previous_siblings属性,可以对当前节点的兄弟节点迭代输出。

回退和前进

.next_element 和 .previous_element属性指向解析过程中的下一个或者上一个解析对象。

.next_elements 和 .previous_elements属性,上或者下解析内容,列表。

搜索文档树

查找解析文档中的标签节点

#1、传入字符串
soup.find_all('b')#查找所有<b>标签
#2、正则表达式
import re
for tag in soup.find_all(re.compile('^b')):
print(tag.name)
#3、传入列表参数
soup.find_all(['a','b'])#查找所有的<a><b>标签
#4、True参数,可以匹配任何值,
#5、如果没有合适的过滤器,还可以定义一个方法,方法只接受一个元素参数,如果这个方法返回True,表示匹配到元素
def has_class_but_no_id(tag):
return tag.has_attr('class') and not tag.has_attr('id')
#可以将上面方法传入find_all()方法
soup.find_all(has_class_but_no_id)
#通过一个方法来过滤一类-标签属性-的时候,这个方法的参数是要被过滤的属性的值,而不是这个标签。
def not_lacie(href):
return href and not re.compile('lacie').search(href)
soup.find_all(href=not_lacie)#找出href属性不符合指定正则的标签。

find_all()方法

find_all( name , attrs , recursive , string , **kwargs )

搜索当前tag的所有子节点,并且判断是否符合过滤器的条件

#name参数,查找所有名字为name的tag,字符串对象被忽略。
soup.find_all('title')
#keyword参数,如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索。
soup.find_al(id='link2')
soup.find_all(href=re.compile('elsie'))
#如果多个指定名字的参数可以同时过滤tag的多个属性:
soup.find_all(href=re.compile('elsie'),id='link1')
#有些tag属性在搜索不能使用,比如HTML5中的data*属性,但是可以通过find_all()的attrs参数定义一个字典来搜索:
data_soup.find_all(attrs={'data-foo':'value'})

按css搜索

#BS4.1开始,可以通过class_参数搜索具有指定css类名的tag:
soup.find_all('a',class_='sister')
#接受通过类型的过滤器,比如正则表达式
soup.find_all(class_=re.compile('it1'))

string参数

soup.find_all(string='Elsie')

limit参数

可以用来限制返回结果的数量

recursive参数

如果指向搜索tag的直接子节点,可以使用参数recursive=False。

像调用find_all()一样来调用tag

每个tag对象可以被当作一个方法来使用,与调用find_all()方法相同。

soup.find_all('a')
soup('a')#这两句代码时等价的

find()方法

与find_all()相同的用法,但是只能返回一个结果。

CSS选择器,select方法

soup.select('title')#选择title标签
soup.select('p nth-of-type(3)') #通过tag标签逐层查找
soup.select('body a')#查找body标签下面的a标签
#找到某个tag标签下的直接子标签:
soup.select('head>title')
#通过id来查找:
soup.select('#link1')
#通过class来查找:
soup.select('.sister')
soup.select('[class~=sister]')
#通过是否存在某个属性来查找:
soup.select('a[href]')
#通过属性的值来查找:
soup.select('a[href="http://www.baidu.com"]')

如果您觉得感兴趣的话,可以添加我的微信公众号:一步一步学Python

爬虫入门【3】BeautifulSoup4用法简介的更多相关文章

  1. 【爬虫入门01】我第一只由Reuests和BeautifulSoup4供养的Spider

    [爬虫入门01]我第一只由Reuests和BeautifulSoup4供养的Spider 广东职业技术学院  欧浩源 1.引言  网络爬虫可以完成传统搜索引擎不能做的事情,利用爬虫程序在网络上取得数据 ...

  2. Python爬虫入门之Urllib库的高级用法

    1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Headers 的属性. 首先,打开我们的浏览 ...

  3. Python爬虫入门四之Urllib库的高级用法

    1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Headers 的属性. 首先,打开我们的浏览 ...

  4. 转 Python爬虫入门四之Urllib库的高级用法

    静觅 » Python爬虫入门四之Urllib库的高级用法 1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我 ...

  5. 爬虫入门四 re

    title: 爬虫入门四 re date: 2020-03-14 16:49:00 categories: python tags: crawler 正则表达式与re库 1 正则表达式简介 编译原理学 ...

  6. 爬虫入门二 beautifulsoup

    title: 爬虫入门二 beautifulsoup date: 2020-03-12 14:43:00 categories: python tags: crawler 使用beautifulsou ...

  7. Python简单爬虫入门三

    我们继续研究BeautifulSoup分类打印输出 Python简单爬虫入门一 Python简单爬虫入门二 前两部主要讲述我们如何用BeautifulSoup怎去抓取网页信息以及获取相应的图片标题等信 ...

  8. Python爬虫入门一之综述

    大家好哈,最近博主在学习Python,学习期间也遇到一些问题,获得了一些经验,在此将自己的学习系统地整理下来,如果大家有兴趣学习爬虫的话,可以将这些文章作为参考,也欢迎大家一共分享学习经验. Pyth ...

  9. Docker新手入门:基本用法

    Docker新手入门:基本用法 1.Docker简介 1.1 第一本Docker书 工作中不断碰到Docker,今天终于算是正式开始学习了.在挑选系统学习Docker以及虚拟化技术的书籍时还碰到了不少 ...

随机推荐

  1. tensorflow BasicRNNCell调试

    运行以下代码,进入~/anaconda3/lib/python3.5/site-packages/tensorflow/python/ops/rnn.py和~/anaconda3/lib/python ...

  2. scrapy爬虫 函数间传值简易教程

    2017-03-27 有的时候我们爬取数据的时候需要在多个页面之间跳转,爬取完所有页面的数据的时候才能把所有数据一起存到数据库,这个时候我们就需要把某个函数内爬取的数据传到下一个函数当中.有人可能会说 ...

  3. zabbix agent监控主机配置

    zabbix agent监控主机配置 环境说明 系统版本    CentOS 7.2 x86_64 软件版本    zabbix 3.0.18   1.监控zabbix服务器端 1.1 安装zabbi ...

  4. linux下rar包的解压方法

    linux下rar包的解压方法 学习了:https://blog.csdn.net/yonggeit/article/details/72190246?utm_source=itdadao&u ...

  5. Json,String,Map之间的转换

    前提是String的格式是map或json类型的 String 转Json JSONObject  jasonObject = JSONObject.fromObject(str); String 转 ...

  6. Java取得操作系统的临时目录

    一般来说,程序员用Eclipse在Windows上编程,而会将war/ear包发布到Linux的服务器上. 涉及临时文件输出的话需要找一个临时目录,下面的语句就能帮你获得不分操作系统的临时目录 Str ...

  7. 在windows上一键编译各种版本的protobuf(2017-12-05修改)

    所需工具 : cmake  for  windows 和  git for windows 原理:protobuf 是google的一个开源项目,其源代码在github上可以下载到,并且源码都采用cm ...

  8. Android 开发 Eclipse使用SVN

    1 help--->install new software--->add 2 name自定义 location填入内容见3 3 http://subclipse.tigris.org/s ...

  9. 在Ubuntu 16.04下安装 virtualbox 5.2

        sudo sh -c 'echo "deb http://download.virtualbox.org/virtualbox/debian xenial contrib" ...

  10. UIWebView的全屏截图

    项目开发中,我们可能会遇到如下的应用场景:将一篇文章,进行截屏(需要全屏截取,包括滚动部分)后,分享到新浪微博.邮箱等等.前段时间,我在应用开发中实现了该功能,代码也是从网上找到的,自己整理了一下.主 ...