python tag对象下有多个标签、属性_Python BeautifulSoup使用教程|Tag对象,HTML标签,Attributes,,find_all,attrs参数,limit,recur...
这是一个专门用于从HTML或XML文件中提取数据的Python库。具体而言,它能够将带有标签标记的HTML或XML文件解析为一种层级结构,并方便地获取到各个标签对应的属性信息。借助Beautiful Soup库工具,我们可以通过指定特定class或id属性来访问所需的数据。
当前最新的 Beautiful Soup 版本为4.8.1。本文示例使用的Python版本为3.7。
Mac系统,直接通过命令安装库:
sudo easy_install beautifulsoup4
安装完成后,尝试包含库运行:
from bs4 import BeautifulSoup
若没有报错,则说明库已正常安装完成。
windows直接用pycharm安装如下图:
开始
本文会通过这个网页:https://www.pythonf.cn/ 来进行示例讲解,如下图所示
BeautifulSoup 对象初始化
当我们将一段文本导入到BeautifulSoup的构建函数中时(例如以下代码片段中),就能生成一个相应的文档对象。具体来说,在这段代码中
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
'User-Agent': 'Common User Agent String'
# 替换为更简洁的标准表达
[
{
'Name': 'Mozilla',
'Version': '5.0'
},
{
'Platform': 'Windows',
'Build': '(10.0; Win64; x64)'
},
{
'AppEngine': '(KHTML, like Gecko)',
# 替换为中文解释
# 使用跨站脚本安全机制(SSE)
},
{
'Browser': 'Chrome',
# 替换为更符合中文习惯的表达
# Chrome版本号: 75.0.(377).1
},
{
'PlatformId': 'Safari'
}
]
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
BeautifulSoup 创建函数的第二个参数用于指定XML解析器,默认情况下会根据输入文档选择合适的解析工具。如果省略此参数,则oup解释器将自动选最适选项进行处理;但这种做法可能会发出警告提示信息。
另外一种途径是通过文件句柄来进行初始化操作。具体步骤如下:可以先把本地同级目录reo.html中的HTML源码进行读取,并将其保存为本地html文件后再进行后续操作。
soup = BeautifulSoup(open('reo.html'))
能够打印 soup,并确保输出内容与HTML文本完全一致;此时该结构为一个复杂的树形组织,并且每个节点均为Python对象。
Ps. 接下来示例代码中所用到的 soup 都为该soup。
Tag
标记实体在Markdown中与DOM API中的标准标签具有相同的名称和功能,在编写脚本时可以直接引用对应的命名空间以实现对内容对象的引用和操作。#coding:UTF-8frombs4 importBeautifulSoup
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
'User-Agent字段': 'Mozilla浏览器/(Windows 10专业版操作系统; 64位版本)使用了类似于Gecko引擎的行为方式,并基于Safari浏览器进行了优化'
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
tag = soup.title
print(tag)
打印结果:
Name
通过Tag对象的name属性,可以获取到标签的名称tag = soup.title
print(tag.name)
Attributes
一个tag通常包含多个属性(例如id、class等),其操作方式类似于字典的操作方式。
例如网页中导航栏标签 nav
获取它 class 属性的值#coding:utf-8frombs4 importBeautifulSoup
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
'User-Agent': '基于 Mozilla 的浏览器框架 (Windows 64位系统扩展; x64位架构) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36')
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
tag = soup.nav
c = tag['class']
print(c)
另一种方式可以直接使用 .attrs 获取全部属性信息,并导入BeautifulSoup类。
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
'User Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770 Safari/537.36'}
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
tag = soup.nav
attrs = tag.attrs
print(attrs)
ps. 因为class属于多值属性,所以它的值为数组。
tag中的字符串
采用 string 方法提取标签中的字符串内容```python import ... beautifulsoup4 import beautifulsoup``
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
User-Agent
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
tag = soup.title
s = tag.string
print(s)
子节点
利用Tag的名称能够访问对应标签;反复调用该方法,则能够访问子节点中的相应标签。
如下图:
我们致力于解析出nav标签中的li#coding:utf-8frombs4 importBeautifulSoup内容
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
tag = soup.nav.li
print(tag)
打印结果:
仅能通过属性属性访问第一个tag。如欲获取全部li标签,则可使用find_all()方法来实现。#coding:utf-8frombs4 importBeautifulSoup
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
tag = soup.nav.find_all('li')
print(tag)
获取到的是包含所有li标签的列表。
tag的 .contents 属性能够将tag的所有子节点以列表形式实现输出:#coding:utf-8frombs4 importBeautifulSoup
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
User-Agent字段:基于 Mozilla 的 Web 应用程序,适用于 Windows 系统的 10 次方版本、64 位架构;该应用包含基于 AppleWebKit 的 Web 内核,并采用类似于 Gecko 的机制进行渲染;同时支持版本号为 Chrome 75.0.3770.100的浏览器应用程序;最后运行于基于 Safari 浏览器的应用程序上。
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
tag = soup.nav.ul
contents = tag.contents
print(contents)
打印目录可以看到列表中不仅包含li标签内容还包含换行符字符\n
通过迭代器遍历tag的所有子节点,该迭代器可实现对相应DOM元素的逐个访问#coding:utf-8frombs4 importBeautifulSoup
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
'UserAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.29 (KHTML, like Gecko) Chrome/75.0 Safari/537.29'}
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
tag = soup.nav.ul
children = tag.children
print(children)
forchild inchildren:
print(child)
父节点
利用.parent属性获取指定元素的父节点;其中其父节点为 body。#coding:utf-8frombs4 importBeautifulSoup
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
tag = soup.nav
print(tag.parent.name)
可利用 .parents 属性来遍历所有父节点。\n# coding: utf-8\nfrom bs4 import BeautifulSoup
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
tag = soup.nav
forp intag.parents:
print(p.name)
兄弟节点
.next_sibling 和 .previous_sibling 成员用于辅助插入相邻节点的方式与其它成员相似。
find_all()
find_all(name , attrs , recursive , string , ** kwargs)
name 参数
查找所有名字为 name 的tag#coding:utf-8frombs4 importBeautifulSoup
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
{'_type': 'text', '$value': '该设备的信息如下:'}
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
print(soup.find_all('title'))
print(soup.find_all('li'))
keyword 参数
如果设置某个参数名称不在内置参数列表中(如name、attrs、recursive、string),那么该参数会被视为与 tag 相关的属性参与搜索;若未指定 tag,则默认对所有 tag 进行搜索。
例如,在代码中可以通过BeautifulSoup库查找所有具有 id 属性值为 footer 的标签#coding:utf-8frombs4 importBeautifulSoup。
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
Technical specifications of the User-Agent:
Browser vendor:
Vendor, e.g., Mozilla, on Windows platform running on Windows 10 series with 64-bit architecture and x64 compatibility;
Browsers engine:
Apple Web Kit (e.g., Chrome);
Self-Service Safari version number:
Safari/537.36
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
print(soup.find_all(id='key'))
加上标签的参数
soup.find_all('input', id='key')
遍历所有具有class属性值为'navigation bar-collapse'的div元素,并导入BeautifulSoup模块。
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
'User-Agent属性': '第五版本 Windows系统第10版本 WindowsNT x64位架构 MozillaAppletext then AppleWebKit (KHTML, like Gecko) then then then Safari/Safari',
'User-Agent': 'Fifth version of Windows system version 10 x64 architecture and engine rendering webpages',
'User-Agent': 'Fifth version of Windows system version 10 x64 architecture and engine rendering webpages'
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
print(soup.find_all('div', class_='collapse navbar-collapse'))
需要特别注意的一点是,在Python编程语言中使用类名时通常会遇到一些特殊要求。由于class是一个保留关键字,在作为参数引用时需特别处理以避免冲突,并在此情况下添加下划线符号以区分标识符。具体来说,在这种情况下标识符被表示为class_。
指定名字的属性参数值可以包括:字符串、正则表达式、列表、True/False。
True/False
是否存在指定的属性。
提取包含 action 属性的所有标签#coding: utf-8frombs4 importBeautifulSoup
fromurllib importrequest
url = 'https://pythonf.cn'headers = {
'User-Agent': '$$Mozilla/(Windows NT 10.0; Win64; x64) AppleWebKit/(537.36+KHTML, like Gecko) Chrome/(75.0.3770.1)\S/Safari/(537.36)'
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
print(soup.find_all(action=True))
在仔细查看时会发现,预期的结果中可能会包含一些具有action属性的标签。需要注意的是,在实际操作中找到的是那些未标注有action属性的主要类标籤
soup.find_all(action=False)
可以指定多个参数作为过滤条件:
搜索 src 属性中包含 python字符串,并且 class 为 lazy 的标签:
soup.find_all(src=re.compile("python"), class_='lazy')
某些属性不具备直接作为参数的能力,在这些情况下需要特别处理。例如数据类型的特定标记如data-****通常无法直接被解析为有效的属性引用。在之前的案例中提到的数据项 data-original 就不具备直接作为参数的能力,并且运行时会出现语法错误,并返回提示信息:keyword cannot serve as an expression。
attrs 参数
定义一个字典参数用于查找对应属性的tag,在某种程度上能够缓解上述提到无法将某些属性作为参数的问题
例如,搜索包含 data-original 属性的标签
print soup.find_all(attrs={'data-original': True})
搜索 data-original 属性中包含pythonf字符串的标签
soup.find_all(attrs={'data-original': re.compile("pythonf")})
搜索 data-original 属性为指定值的标签
soup.find_all(attrs={'data-original': 'www.pythonf.cn'})
string 参数
和 name 参数类似,针对文档中的字符串内容。
搜索包含 ‘教程’字符串的标签:#coding:utf-8frombs4 importBeautifulSoup
fromurllib importrequest
importre
url = 'https://pythonf.cn'headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
print(soup.find_all(string=re.compile("教程")))
结果见下图所示:
limit 参数
该函数的作用是获取整个文档的所有搜索结果...当处理的文档信息量较大时...并附加一个limit参数用于控制最大返回数量...一旦累积的结果数目达到指定的limit值,则立即终止搜索,并将当前收集到的结果返回给调用者。
搜索 class 为 row 的 div 标签,只搜索3个
soup.find_all('div', class_='row', limit=3)
生成一个包含三个元素的列表,在文档中每个元素的标签标识符超过三个
recursive 参数
find_all() 负责查找当前tag的所有子节点。如果不希望进行深入搜索,则可以通过设置参数recursive为False来实现。
find()
find(name , attrs , recursive , string , ** kwargs)
这两个方法的参数使用相似,在功能上几乎相同;然而,在搜索结果数量方面存在显著差异:find() 只会返回单个结果(即第一个符合条件的结果),而要获得与 find_all() 相同的效果,则需要将 limit 设置为 1
soup.find('div', class_='row')
搜索结果保持一致,在主要区别上在于:find_all() 返回的结果是一个数组形式的数据结构,而 find() 则返回单个元素的形式。
当未找到符合要求的标签时,find()操作的结果为None, 而另一方面,find_all()操作的结果为空列表。
CSS选择器
HTML标签或BeautifulSoup对象可以通过select()方法接收一个字符串参数, 即可利用CSS选择器的语法获取所需标签
确保语义与CSS保持一致,并在nav标签下的ul标签中查找li标签。#! coding utf-8 from bs4 import BeautifulSoup
fromurllib importrequest
importre
url = 'https://pythonf.cn'headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
req = request.Request(url, headers=headers)
response = request.urlopen(req)
content = response.read()
soup = BeautifulSoup(content, 'html.parser')
print(soup.select('nav ul li'))
通过类名查找,两行代码的结果一致,搜索 class 为 thumb 的标签
soup.select('.row')
soup.select('[class~=row]')
通过id查找,搜索 id 为 sponsor 的标签
soup.select('#key')
通过是否存在某个属性来查找,搜索具有 id 属性的 li 标签
soup.select('li[id]')
通过属性的值来查找查找,搜索 id 为 sponsor 的 li 标签
soup.select('li[id="key"]')
其他
其他的搜索方法还有:
find_parents() 和 find_parent()
find_next_siblings() 和 find_next_sibling()
find_previous_siblings() 和 find_previous_sibling()
…
参数的作用大致与 find\_all\(\) 和 find\(\) 相似,在这里就不再详细说明它们的具体使用方法了。这两个方法基本上能满足大部分查询的需求。
还有一些方法会修改文档结构。对于网络爬虫而言,大部分任务都是从网页中提取信息,并不需要深入修改原始代码,因此这些内容就不再详细说明了
具体详细信息可直接参考Beautiful Soup库的官方说明文档。
