网络爬虫--16.BeautifulSoup4

文章目录

  • 一. BeautifulSoup4
  • 二. 解析实例
  • 三. 四大对象种类
    • 1. Tag
    • 2. NavigableString
    • 3. BeautifulSoup
    • 4. Comment
  • 四. 遍历文档树
    • 1.直接子节点 :.contents .children 属性
      • 1). .contents
      • 2). .children
    • 2. 所有子孙节点: .descendants 属性
    • 3. 节点内容: .string 属性
  • 五. 搜索文档树
    • 1. find_all(name, attrs, recursive, text, **kwargs)
      • 1). name 参数
      • 2). keyword 参数
      • 3).text 参数
    • 2. CSS选择器
      • 1). 通过标签名查找
      • 2). 通过类名查找
      • 3).通过 id 名查找
      • 4).组合查找
      • 5). 属性查找
      • 6). 获取内容

一. BeautifulSoup4

官方文档:http://beautifulsoup.readthedocs.io/zh_CN/v4.4.0

和 lxml 一样,Beautiful Soup 也是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 数据。

lxml 只会局部遍历,而Beautiful Soup 是基于HTML DOM的,会载入整个文档,解析整个DOM树,因此时间和内存开销都会大很多,所以性能要低于lxml。

BeautifulSoup 用来解析 HTML 比较简单,API非常人性化,支持CSS选择器、Python标准库中的HTML解析器,也支持 lxml 的 XML解析器。

Beautiful Soup 3 目前已经停止开发,推荐现在的项目使用Beautiful Soup 4。使用 pip 安装即可:pip install beautifulsoup4

在这里插入图片描述

二. 解析实例

首先必须要导入 bs4 库

from bs4 import BeautifulSouphtml = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>
"""#创建 Beautiful Soup 对象
soup = BeautifulSoup(html)#打开本地 HTML 文件的方式来创建对象
#soup = BeautifulSoup(open('index.html'))#格式化输出 soup 对象的内容
print soup.prettify()

输出结果:

<html><head><title>The Dormouse's story</title></head><body><p class="title" name="dromouse"><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>

运行后会看到这样一段警告:

UserWarning: No parser was explicitly specified, so I'm using the best available HTML parser for this system ("lxml"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently.The code that caused this warning is on line 18 of the file D:/PycharmProject/spider/spider24_BeautifulSoup1.py. To get rid of this warning, pass the additional argument 'features="lxml"' to the BeautifulSoup constructor.soup = BeautifulSoup(html)

在这里插入图片描述
意思是,如果我们没有显式地指定解析器,所以默认使用这个系统的最佳可用HTML解析器(“lxml”)。如果你在另一个系统中运行这段代码,或者在不同的虚拟环境中,使用不同的解析器造成行为不同。

但是我们可以通过soup = BeautifulSoup(html,“lxml”)方式指定lxml解析器

三. 四大对象种类

Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:

  • Tag
  • NavigableString
  • BeautifulSoup
  • Comment

1. Tag

Tag 通俗点讲就是 HTML 中的一个个标签,例如:title head a p等等 HTML 标签加上里面包括的内容就是 Tag,那么试着使用 Beautiful Soup 来获取 Tags:

from bs4 import BeautifulSouphtml = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>
"""#创建 Beautiful Soup 对象
soup = BeautifulSoup(html)print soup.title
# <title>The Dormouse's story</title>print soup.head
# <head><title>The Dormouse's story</title></head>print soup.a
# <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>print soup.p
# <p class="title" name="dromouse"><b>The Dormouse's story</b></p>print type(soup.p)
# <class 'bs4.element.Tag'>

我们可以利用 soup 加标签名轻松地获取这些标签的内容,这些对象的类型是bs4.element.Tag。但是注意,它查找的是在所有内容中的第一个符合要求的标签。如果要查询所有的标签,后面会进行介绍。

对于 Tag,它有两个重要的属性,是 name 和 attrs

print soup.name
# [document] #soup 对象本身比较特殊,它的 name 即为 [document]print soup.head.name
# head #对于其他内部标签,输出的值便为标签本身的名称print soup.p.attrs
# {'class': ['title'], 'name': 'dromouse'}
# 在这里,我们把 p 标签的所有属性打印输出了出来,得到的类型是一个字典。print soup.p['class'] # soup.p.get('class')
# ['title'] #还可以利用get方法,传入属性的名称,二者是等价的soup.p['class'] = "newClass"
print soup.p # 可以对这些属性和内容等等进行修改
# <p class="newClass" name="dromouse"><b>The Dormouse's story</b></p>del soup.p['class'] # 还可以对这个属性进行删除
print soup.p
# <p name="dromouse"><b>The Dormouse's story</b></p>

2. NavigableString

既然我们已经得到了标签的内容,那么问题来了,我们要想获取标签内部的文字怎么办呢?很简单,用 .string 即可,例如

print soup.p.string
# The Dormouse's storyprint type(soup.p.string)
# In [13]: <class 'bs4.element.NavigableString'>

3. BeautifulSoup

BeautifulSoup 对象表示的是一个文档的内容。大部分时候,可以把它当作 Tag 对象,是一个特殊的 Tag,我们可以分别获取它的类型,名称,以及属性来感受一下

print type(soup.name)
# <type 'unicode'>print soup.name 
# [document]print soup.attrs # 文档本身的属性为空
# {}

4. Comment

Comment 对象是一个特殊类型的 NavigableString 对象,其输出的内容不包括注释符号。

print soup.a
# <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>print soup.a.string
# Elsie print type(soup.a.string)
# <class 'bs4.element.Comment'>

a 标签里的内容实际上是注释,但是如果我们利用 .string 来输出它的内容时,注释符号已经去掉了。

四. 遍历文档树

1.直接子节点 :.contents .children 属性

1). .contents

tag 的 .content 属性可以将tag的子节点以列表的方式输出

print soup.head.contents 
#[<title>The Dormouse's story</title>]

输出方式为列表,我们可以用列表索引来获取它的某一个元素

print soup.head.contents[0]
#<title>The Dormouse's story</title>

2). .children

它返回的不是一个 list,不过我们可以通过遍历获取所有子节点。

我们打印输出 .children 看一下,可以发现它是一个 list 生成器对象

print soup.head.children
#<listiterator object at 0x7f71457f5710>for child in  soup.body.children:print child

结果:

<p class="title" name="dromouse"><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>

2. 所有子孙节点: .descendants 属性

.contents 和 .children 属性仅包含tag的直接子节点,.descendants 属性可以对所有tag的子孙节点进行递归循环,和 children类似,我们也需要遍历获取其中的内容。

for child in soup.descendants:print child

运行结果:

<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>
<head><title>The Dormouse's story</title></head>
<title>The Dormouse's story</title>
The Dormouse's story<body>
<p class="title" name="dromouse"><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><p class="title" name="dromouse"><b>The Dormouse's story</b></p>
<b>The Dormouse's story</b>
The Dormouse's story<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>
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>Elsie 
,<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
Lacieand<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
Tillie
;
and they lived at the bottom of a well.<p class="story">...</p>
...

3. 节点内容: .string 属性

如果tag只有一个 NavigableString 类型子节点,那么这个tag可以使用 .string 得到子节点。如果一个tag仅有一个子节点,那么这个tag也可以使用 .string 方法,输出结果与当前唯一子节点的 .string 结果相同。

通俗点说就是:如果一个标签里面没有标签了,那么 .string 就会返回标签里面的内容。如果标签里面只有唯一的一个标签了,那么 .string 也会返回最里面的内容。例如:

print soup.head.string
#The Dormouse's story
print soup.title.string
#The Dormouse's story

五. 搜索文档树

1. find_all(name, attrs, recursive, text, **kwargs)

1). name 参数

name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉

A.传字符串
最简单的过滤器是字符串.在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容,下面的例子用于查找文档中所有的< b>标签:

soup.find_all('b')
# [<b>The Dormouse's story</b>]print soup.find_all('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>]

B.传正则表达式
如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,这表示< body>和< b>标签都应该被找到

import re
for tag in soup.find_all(re.compile("^b")):print(tag.name)
# body
# b

C.传列表
如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有< a>标签和< b>标签:

soup.find_all(["a", "b"])
# [<b>The Dormouse's story</b>,
#  <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>]

2). keyword 参数

soup.find_all(id='link2')
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

3).text 参数

soup.find_all(text="Elsie")
# [u'Elsie']soup.find_all(text=["Tillie", "Elsie", "Lacie"])
# [u'Elsie', u'Lacie', u'Tillie']soup.find_all(text=re.compile("Dormouse"))
[u"The Dormouse's story", u"The Dormouse's story"]

2. CSS选择器

这就是另一种与 find_all 方法有异曲同工之妙的查找方法.

  • 写 CSS 时,标签名不加任何修饰,类名前加.,id名前加#
  • 在这里我们也可以利用类似的方法来筛选元素,用到的方法是 soup.select(),返回类型是 list

1). 通过标签名查找

print soup.select('title') 
#[<title>The Dormouse's story</title>]print soup.select('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>]print soup.select('b')
#[<b>The Dormouse's story</b>]

2). 通过类名查找

print soup.select('.sister')
#[<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>]

3).通过 id 名查找

print soup.select('#link1')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

4).组合查找

组合查找即和写 class 文件时,标签名与类名、id名进行的组合原理是一样的,例如查找 p 标签中,id 等于 link1的内容,二者需要用空格分开

print soup.select('p #link1')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

直接子标签查找,则使用 > 分隔

print soup.select("head > title")
#[<title>The Dormouse's story</title>]

5). 属性查找

查找时还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。

print soup.select('a[class="sister"]')
#[<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>]print soup.select('a[href="http://example.com/elsie"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

同样,属性仍然可以与上述查找方式组合,不在同一节点的空格隔开,同一节点的不加空格

print soup.select('p a[href="http://example.com/elsie"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

6). 获取内容

以上的 select 方法返回的结果都是列表形式,可以遍历形式输出,然后用 get_text() 方法来获取它的内容。

soup = BeautifulSoup(html, 'lxml')
print type(soup.select('title'))
print soup.select('title')[0].get_text()for title in soup.select('title'):print title.get_text()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/451990.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LA3415 训练指南】保守的老师 【二分图最大独立集,最小割】

题意 Frank是一个思想有些保守的高中老师。有一次&#xff0c;他需要带一些学生出去旅行&#xff0c;但又怕其中一些学生在旅行中萌生爱意。为了降低这种事情发生的概率&#xff0c;他决定确保带出去的任意两个学生至少要满足下面四条中的一条。 1.身高相差大于40厘米 2.性别相…

行车记录仪稳定方案:TC358778XBG:RGB转MIPI DSI芯片,M-Star标配IC

原厂&#xff1a;Toshiba型号&#xff1a;TC358778XBG功能&#xff1a;TC358778XBG是一颗将RGB信号转换成MIPI DSI的芯片&#xff0c;最高分辨率支持到1920x1200&#xff0c;其应用图如下&#xff1a;产品特征&#xff1a;MIPI接口&#xff1a;&#xff08;1&#xff09;、支持…

java.sql.SQLException: 无法转换为内部表示之解决

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 这个错是因为 数据库中字段类型和程序中该字段类型不一致。 比如程序将某字段当做Integer类型&#xff0c; 而数据库存储又使用另外一…

网络爬虫--17.【BeautifuSoup4实战】爬取腾讯社招

文章目录一.要求二.代码示例一.要求 以腾讯社招页面来做演示&#xff1a;http://hr.tencent.com/position.php?&start10#a 使用BeautifuSoup4解析器&#xff0c;将招聘网页上的职位名称、职位类别、招聘人数、工作地点、发布时间&#xff0c;以及每个职位详情的点击链接…

彻底搞清楚Android中的 Attr

版权声明&#xff1a;本文为sydMobile原创文章&#xff0c;转载请务必注明出处&#xff01; https://blog.csdn.net/sydMobile/article/details/79978187 相信这个词对于Android开发者来说十分熟悉了&#xff0c;那么你对他到底有多了解呢&#xff1f; 回忆起我刚开始接触Andr…

D. Relatively Prime Graph

Lets call an undirected graph G(V,E)G(V,E) relatively prime if and only if for each edge (v,u)∈E(v,u)∈E GCD(v,u)1GCD(v,u)1 (the greatest common divisor of vv and uu is 11). If there is no edge between some pair of vertices vv and uu then the value of GC…

网络爬虫--19.【Scrapy-Redis实战】分布式爬虫爬取房天下--环境准备

文章目录0. 思路一. 虚拟机Ubuntu0中安装Redis二. 虚拟机Ubuntu1中安装Redis三. Windows服务器上安装Redis四. 安装cmder五. 安装RedisDesktopManager六. 修改Windows中的配置文件redis.windows.conf七. Ubuntu连接Windows上 的Redis服务器-----------------------------------…

tkinter中scale拖拉改变值控件(十一)

scale拖拉改变值控件 使用户通过拖拽改变值 简单的实现&#xff1a; 1 import tkinter2 3 wuya tkinter.Tk() 4 wuya.title("wuya") 5 wuya.geometry("300x2001020") 6 7 8 # 创建对象 9 scale1 tkinter.Scale(wuya, from_0, to100) 10 scale1.pac…

计算机图形学理论(4):缓冲区

本系列根据国外一个图形小哥的讲解为本&#xff0c;整合互联网的一些资料&#xff0c;结合自己的一些理解。 什么是缓冲区&#xff1f; 缓冲区是保存某些数据的临时存储空间。 为什么我们需要缓冲区&#xff1f;原因很简单&#xff0c;当数据量很大时&#xff0c;因为计算机无…

网络爬虫--20.【Scrapy-Redis实战】分布式爬虫获取房天下--代码实现

文章目录一. 案例介绍二.创建项目三. settings.py配置四. 详细代码五. 部署1. windows环境下生成requirements.txt文件2. xshell连接ubuntu服务器并安装依赖环境3. 修改部分代码4. 上传代码至服务器并运行一. 案例介绍 爬取房天下&#xff08;https://www1.fang.com/&#xff…

同一台电脑安装python2python3

【安装之前&#xff0c;先了解一下概念】 python是什么&#xff1f; Python是一种面向对象的解释型计算机程序设计语言&#xff0c;由荷兰人Guido van Rossum于1989年发明&#xff0c;第一个公开发行版发行于1991年。 Python是纯粹的自由软件&#xff0c; 源代码和解释器CPytho…

程序员的常见健康问题

其实这些问题不仅见于程序员&#xff0c;其他长期经常坐在电脑前的职场人士&#xff08;比如&#xff1a;网络编辑、站长等&#xff09;&#xff0c;都会有其中的某些健康问题。希望从事这些行业的朋友&#xff0c;对自己的健康问题&#xff0c;予以重视。以下是全文。 我最近…

网络爬虫--21.Scrapy知识点总结

文章目录一. Scrapy简介二. Scrapy架构图三. Scrapy框架模块功能四. 安装和文档五. 创建项目六. 创建爬虫一. Scrapy简介 二. Scrapy架构图 三. Scrapy框架模块功能 四. 安装和文档 中文文档&#xff1a;https://scrapy-chs.readthedocs.io/zh_CN/latest/intro/tutorial.html …

Ubuntu将在明年推出平板及手机系统

4月26日下午消息&#xff0c;知名Linux厂商Canonical今天正式发布Ubuntu 12.04版开源操作系统。Ubuntu中国首席代表于立强透露&#xff0c;针对平板电脑的Ubuntu操作系统将在明年推出。 Ubuntu 12.04版开源操作系统发布 Ubuntu操作系统是一款开源操作系统&#xff0c;主要与OE…

Android Studio 超级简单的打包生成apk

为什么要打包&#xff1a; apk文件就是一个包&#xff0c;打包就是要生成apk文件&#xff0c;有了apk别人才能安装使用。打包分debug版和release包&#xff0c;通常所说的打包指生成release版的apk&#xff0c;release版的apk会比debug版的小&#xff0c;release版的还会进行混…

推荐16款最棒的Visual Studio插件

Visual Studio是微软公司推出的开发环境&#xff0c;Visual Studio可以用来创建Windows平台下的Windows应用程序和网络应用程序&#xff0c;也可以用来创建网络服务、智能设备应用程序和Office插件。 本文介绍16款最棒的Visual Studio扩展&#xff1a; 1. DevColor Extension…

网络爬虫--22.【CrawlSpider实战】实现微信小程序社区爬虫

文章目录一. CrawlSpider二. CrawlSpider案例1. 目录结构2. wxapp_spider.py3. items.py4. pipelines.py5. settings.py6. start.py三. 重点总结一. CrawlSpider 现实情况下&#xff0c;我们需要对满足某个特定条件的url进行爬取&#xff0c;这时候就可以通过CrawlSpider完成。…

怎么安装Scrapy框架以及安装时出现的一系列错误(win7 64位 python3 pycharm)

因为要学习爬虫&#xff0c;就打算安装Scrapy框架&#xff0c;以下是我安装该模块的步骤&#xff0c;适合于刚入门的小白&#xff1a; 一、打开pycharm&#xff0c;依次点击File---->setting---->Project----->Project Interpreter&#xff0c;打开后&#xff0c;可以…

xpath-helper: 谷歌浏览器安装xpath helper 插件

1.下载文件xpath-helper.crx xpath链接&#xff1a;https://pan.baidu.com/s/1dFgzBSd 密码&#xff1a;zwvb&#xff0c;感谢这位网友&#xff0c;我从这拿到了 2.在Google浏览器里边找到这个“扩展程序”选项菜单即可。 3.然后就会进入到扩展插件的界面了,把下载好的离线插件…