IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 快速入门 Python 爬虫常用解析库(xpath、bs4) -> 正文阅读

[Python知识库]快速入门 Python 爬虫常用解析库(xpath、bs4)

第一章 XPath 解析

在 Python 中可以支持 XPath 提取数据的解析模块有很多,本文主要介绍 lxml 模块,该模块可以解析 HTML 与 XML,并且支持 XPath 解析方式。由于 lxml 模块 为第三方模块,需要通过 pip install lxml 命令安装该模块。lxml 模块 的底层是通过C语言编写的,所以在解析效率方面是非常优秀的。xpath 语法参考学习网站:https://www.w3school.com.cn/xpath/xpath_nodes.asp。

【示例1】使用 parse() 方法解析本地的 HTML 文件。(一般不怎么常用)

笔者在自己本地新建了一个 demo.html,内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>lxml模块读取本地html文件测试</title>
</head>
<body>
hello, lxml!
</body>
</html>

python 代码如下:

from lxml import etree  # 导入etree子模块

parser = etree.HTMLParser()  # 创建HTMLParser对象
html = etree.parse('demo.html', parser=parser)  # 解析demo.html文件
print(type(html))  # <class 'lxml.etree._ElementTree'> 是一个对象
html_txt = etree.tostring(html, encoding="utf-8")  # 转换字符串类型,并进行编码
print(html_txt.decode('utf-8'))  # 打印解码后的HTML代码

【示例2】解析字符串类型的 HTML 代码。etree 子模块还提供了一个 HTML() 方法,该方法可以实现解析字符串类型的 HTML 代码。示例代码如下:

from lxml import etree  # 导入etree子模块

# 定义html字符串
html_str = '''<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>解析字符串类型的 HTML</title>
</head>
<body>
hello, lxml!
</body>
</html>'''
html = etree.HTML(html_str)  # 解析html字符串
html_txt = etree.tostring(html, encoding="utf-8")  # 转换字符串类型,并进行编码
print(html_txt.decode('utf-8'))  # 打印解码后的HTML代码

【示例3】解析服务器返回的 HTML 代码。在实际开发中,HTML() 方法的使用率是非常高的,因为发送网络请求后,多数情况下都会将返回的响应结果转换为字符串类型,如果返回的结果是 HTML 代码,则需要使用 HTML() 方法来进行解析。示例代码如下:

from lxml import etree  # 导入etree子模块
import requests  # 导入requests模块
from requests.auth import HTTPBasicAuth  # 导入HTTPBasicAuth类

# 定义请求地址
url = 'http://sck.rjkflm.com:666/spider/auth/'
# 实现验证请求功能
ah = HTTPBasicAuth('admin', 'admin')  # 创建HTTPBasicAuth对象,参数为用户名与密码
response = requests.get(url=url, auth=ah)  # 发送网络请求
if response.status_code == 200:  # 如果请求成功
    html = etree.HTML(response.text)  # 解析html字符串
    html_txt = etree.tostring(html, encoding="utf-8")  # 转换字符串类型,并进行编码
    print(html_txt.decode('utf-8'))  # 打印解码后的HTML代码
"""
分析: 运行结果中会出现&#13; 表示 Unicode 编码的回车字符。
"""

【示例4】使用 // 获取HTML代码的所有节点 ,示例如下:

html_str = '''
<div class="level_one on">
<ul>
<li> <a href="/index/index/view/id/1.html" title="什么是Java" class="on">什么是Java</a> </li>
<li> <a href="javascript:" οnclick="login(0)" title="Java的版本">Java的版本</a> </li>
<li> <a href="javascript:" οnclick="login(0)" title="Java API文档">Java API文档</a> </li>
<li> <a href="javascript:" οnclick="login(0)" title="JDK的下载">JDK的下载</a> </li>
<li> <a href="javascript:" οnclick="login(0)" title="JDK的安装">JDK的安装</a> </li>
<li> <a href="javascript:" οnclick="login(0)" title="配置JDK">配置JDK</a> </li>
</ul>
</div>
'''
html = etree.HTML(html_str)  # 解析html字符串
node_all = html.xpath('//*')  # 获取所有节点
print('数据类型:', type(node_all))  # 打印数据类型
print('数据长度:', len(node_all))  # 打印数据长度
print('数据内容:', node_all)  # 打印数据内容
# 通过推导式打印所有节点名称,通过节点对象.tag获取节点名称
print('节点名称:', [i.tag for i in node_all])
######################################################
html = etree.HTML(html_str)  # 解析html字符串
li_all = html.xpath('//li')  # 获取所有li节点
print('所有li节点', li_all)  # 打印所有li节点
print('获取指定li节点:', li_all[1])  # 打印指定li节点
li_txt = etree.tostring(li_all[1], encoding="utf-8")  # 转换字符串类型,并进行编码
# 打印指定节点的HTML代码
print('获取指定节点HTML代码:', li_txt.decode('utf-8'))

程序运行结果如下:

数据类型: <class 'list'>
数据长度: 16
数据内容: [<Element html at 0x20aec9e8088>, <Element body at 0x20aecabee48>, <Element div at 0x20aecabef08>, <Element ul at 0x20aecabef48>, <Element li at 0x20aecabef88>, <Element a at 0x20aecac5048>, <Element li at 0x20aecac5088>, <Element a at 0x20aecac50c8>, <Element li at 0x20aecac5108>, <Element a at 0x20aecabefc8>, <Element li at 0x20aecac5148>, <Element a at 0x20aecac5188>, <Element li at 0x20aecac51c8>, <Element a at 0x20aecac5208>, <Element li at 0x20aecac5248>, <Element a at 0x20aecac5288>]
节点名称: ['html', 'body', 'div', 'ul', 'li', 'a', 'li', 'a', 'li', 'a', 'li', 'a', 'li', 'a', 'li', 'a']

所有li节点 [<Element li at 0x20aec9fad48>, <Element li at 0x20aecac5c88>, <Element li at 0x20aecac5d08>, <Element li at 0x20aecac5dc8>, <Element li at 0x20aecac5e08>, <Element li at 0x20aecac5e88>]
获取指定li节点: <Element li at 0x20aecac5c88>
获取指定节点HTML代码: <li> <a href="javascript:" οnclick="login(0)" title="Java的版本">Java的版本</a> </li>

【示例5】使用 / 获取一个节点中的直接子节点,示例如下:

# 定义html字符串
html_str = '''
<div class="level_one on">
<ul>
<li>
    <a href="/index/index/view/id/1.html" title="什么是Java" class="on">什么是Java</a>
    <a>Java</a> 
</li>
<li> <a href="javascript:" οnclick="login(0)" title="Java的版本">Java的版本</a> </li>
<li> <a href="javascript:" οnclick="login(0)" title="Java API文档">Java API文档</a> </li>
</ul>
</div>
'''
html = etree.HTML(html_str)  # 解析html字符串
a_all = html.xpath('//li/a')  # 获取li节点中所有子节点a
print('所有子节点a', a_all)  # 打印所有a节点
print('获取指定a节点:', a_all[1])  # 打印指定a节点
a_txt = etree.tostring(a_all[1], encoding="utf-8")  # 转换字符串类型,并进行编码
# 打印指定节点的HTML代码
print('获取指定节点HTML代码:', a_txt.decode('utf-8'))

程序运行结果如下:

所有子节点a [<Element a at 0x20aecac7a48>, <Element a at 0x20aecac7a88>, <Element a at 0x20aecac7ac8>, <Element a at 0x20aecac7b08>]
获取指定a节点: <Element a at 0x20aecac7a88>
获取指定节点HTML代码: <a>Java</a> 

【示例6】使用 // 实现获取子孙节点,示例如下:

# 定义html字符串
html_str = '''
<div class="level_one on">
<ul>
<li>
    <a href="/index/index/view/id/1.html" title="什么是Java" class="on">什么是Java</a>
    <a>Java</a> 
</li>
<li> <a href="javascript:" οnclick="login(0)" title="Java的版本">Java的版本</a> </li>
<li> 
    <a href="javascript:" οnclick="login(0)" title="Java API文档">
        <a>a节点中的a节点</a>
    </a>
</li>
</ul>
</div>
'''
html = etree.HTML(html_str)    # 解析html字符串
a_all = html.xpath('//ul//a')   # 获取ul节点中所有子孙节点a
print('所有子节点a',a_all)    # 打印所有a节点
print('获取指定a节点:',a_all[4])  # 打印指定a节点
a_txt = etree.tostring(a_all[4],encoding = "utf-8")   # 转换字符串类型,并进行编码
# 打印指定节点的HTML代码
print('获取指定节点HTML代码:',a_txt.decode('utf-8'))

程序运行结果如下:

所有子节点a [<Element a at 0x20aec9e8708>, <Element a at 0x20aecac8388>, <Element a at 0x20aecac83c8>, <Element a at 0x20aecac8408>, <Element a at 0x20aecac8448>]
获取指定a节点: <Element a at 0x20aecac8448>
获取指定节点HTML代码: <a>a节点中的a节点</a>

【示例7】使用 … 获取一个节点的父节点,示例如下:

# 定义html字符串
html_str = '''
<div class="level_one on">
<ul>
<li><a href="/index/index/view/id/1.html" title="什么是Java" class="on">什么是Java</a></li>
<li> <a href="javascript:" οnclick="login(0)" title="Java的版本">Java的版本</a> </li>
</ul>
</div>
'''
html = etree.HTML(html_str)    # 解析html字符串
a_all_parent = html.xpath('//a/..')   # 获取所有a节点的父节点
print('所有a的父节点',a_all_parent)    # 打印所有a的父节点
print('获取指定a的父节点:',a_all_parent[0])  # 打印指定a的父节点
a_txt = etree.tostring(a_all_parent[0],encoding = "utf-8")   # 转换字符串类型,并进行编码
# 打印指定节点的HTML代码
print('获取指定节点HTML代码:\n',a_txt.decode('utf-8'))
# 除了使用“..”获取一个节点的父节点以外,还可以使用“/parent::*”的方式来获取。
# 例子:获取li的父节点
ul = html.xpath("//li/parent::*")
print(ul)

程序运行结果如下:

所有a的父节点 [<Element li at 0x20aee0a8e48>, <Element li at 0x20aee0a8088>]
获取指定a的父节点: <Element li at 0x20aee0a8e48>
获取指定节点HTML代码:
 <li><a href="/index/index/view/id/1.html" title="什么是Java" class="on">什么是Java</a></li>

[<Element ul at 0x20aee0a8a08>]

【示例8】使用 text() 方法获取HTML代码中的文本,示例如下:

# 定义html字符串
html_str = '''
<div class="level_one on">
<ul>
<li><a href="/index/index/view/id/1.html" title="什么是Java" class="on">什么是Java</a></li>
<li> <a href="javascript:" οnclick="login(0)" title="Java的版本">Java的版本</a> </li>
</ul>
</div>
'''
html = etree.HTML(html_str)    # 解析html字符串
a_text = html.xpath('//a/text()')   # 获取所有a节点中的文本信息
print('所有a节点中文本信息:',a_text)

程序运行结果如下:

所有a节点中文本信息: ['什么是Java', 'Java的版本']

【示例9】使用[@…] 实现节点属性的匹配,示例如下:

# 定义html字符串
html_str = '''
<div class="video_scroll">
    <div class="level">什么是Java</div>
    <div class="level">Java的版本</div>
</div>
'''
html = etree.HTML(html_str)    # 解析html字符串
# 获取所有class="level"的div节点中的文本信息 @后面加对应属性名都可
div_one = html.xpath('//div[@class="level"]/text()')
print(div_one)     # 打印class="level"的div中文本

程序运行结果如下:

['什么是Java', 'Java的版本']

【示例10】属性多值匹配进行节点内容的筛选,示例如下:

# 定义html字符串
html_str = '''
<div class="video_scroll">
    <div class="level one">什么是Java</div>
    <div class="level">Java的版本</div>
</div>
'''
html = etree.HTML(html_str)    # 解析html字符串
# 获取所有class="level one"的div节点中的文本信息
div_one = html.xpath('//div[@class="level one"]/text()')
print(div_one)     # 打印class="level one"的div中文本


html = etree.HTML(html_str)    # 解析html字符串
# 获取所有class属性值中包含level的div节点中的文本信息
div_all = html.xpath('//div[contains(@class,"level")]/text()')
print(div_all)     # 打印所有符合条件的文本信息

程序运行结果如下:

['什么是Java']
['什么是Java', 'Java的版本']

【示例11】一个节点中多个属性的匹配,示例如下:

# 定义html字符串
html_str = '''
<div class="video_scroll">
    <div class="level" id="one">什么是Java</div>
    <div class="level">Java的版本</div>
</div>
'''
html = etree.HTML(html_str)    # 解析html字符串
# 获取所有符合class="level与id="one"的div节点中的文本信息
div_all = html.xpath('//div[@class="level" and @id="one"]/text()')
print(div_all)     # 打印所有符合条件的文本信息

程序运行结果如下:

['什么是Java']

【示例12】使用 @获取属性所对应的值,示例如下:

# 定义html字符串
html_str = '''
<div class="video_scroll">
    <li class="level" id="one">什么是Java</li>
</div>
'''
html = etree.HTML(html_str)    # 解析html字符串
# 获取li节点中的class属性值
li_class = html.xpath('//div/li/@class')
# 获取li节点中的id属性值
li_id = html.xpath('//div/li/@id')
print('class属性值:',li_class)
print('id属性值:',li_id)

程序运行结果如下:

class属性值: ['level']
id属性值: ['one']

【示例13】使用索引按序获取属性对应的值,示例如下:

# 定义html字符串
html_str = '''
<div class="video_scroll">
    <li> <a href="javascript:" οnclick="login(0)" title="Java API文档">Java API文档</a> </li>
    <li> <a href="javascript:" οnclick="login(0)" title="JDK的下载">JDK的下载</a> </li>
    <li> <a href="javascript:" οnclick="login(0)" title="JDK的安装">JDK的安装</a> </li>
    <li> <a href="javascript:" οnclick="login(0)" title="配置JDK">配置JDK</a> </li>
</div>
'''
html = etree.HTML(html_str)    # 解析html字符串
# 获取所有li/a节点中title属性值
li_all = html.xpath('//div/li/a/@title')
print('所有属性值:',li_all)  
# 获取第1个li/a节点中title属性值
li_first = html.xpath('//div/li[1]/a/@title')
print('第一个属性值:',li_first)  # 最后的结果哪怕只有一个,也是以列表的形式进行返回
# 获取第4个li/a节点中title属性值
li_four = html.xpath('//div/li[4]/a/@title')
print('第四个属性值:',li_four)



html = etree.HTML(html_str)    # 解析html字符串
# 获取最后一个li/a节点中title属性值
li_last = html.xpath('//div/li[last()]/a/@title')
print('最后一个属性值:',li_last)
# 获取第1个li/a节点中title属性值
li = html.xpath('//div/li[position()=1]/a/@title')
print('第一个位置的属性值:',li)
# 获取倒数第二个li/a节点中title属性值
li = html.xpath('//div/li[last()-1]/a/@title')
print('倒数第二个位置的属性值:',li)
# 获取位置大于1的li/a节点中title属性值
li = html.xpath('//div/li[position()>1]/a/@title')
print('位置大于1的属性值:',li)

程序运行结果如下:

所有属性值: ['Java API文档', 'JDK的下载', 'JDK的安装', '配置JDK']
第一个属性值: ['Java API文档']
第四个属性值: ['配置JDK']
最后一个属性值: ['配置JDK']
第一个位置的属性值: ['Java API文档']
倒数第二个位置的属性值: ['JDK的安装']
位置大于1的属性值: ['JDK的下载', 'JDK的安装', '配置JDK']

【示例14】使用节点轴获取节点内容,示例如下:

# 定义html字符串
html_str = '''
<div class="video_scroll">
    <li><a href="javascript:" οnclick="login(0)" title="Java API文档">Java API文档</a></li> 
    <li><a href="javascript:" οnclick="login(0)" title="JDK的下载">JDK的下载</a></li> 
    <li> <a href="javascript:" οnclick="login(0)" title="JDK的安装">JDK的安装</a> </li>
</div>
'''

html = etree.HTML(html_str)    # 解析html字符串
# 获取li[2]所有祖先节点
ancestors = html.xpath('//li[2]/ancestor::*')
print('li[2]所有祖先节点名称:',[i.tag for i in ancestors])
# 获取li[2]祖先节点位置为body
body = html.xpath('//li[2]/ancestor::body')
print('li[2]指定祖先节点名称:',[i.tag for i in body])
# 获取li[2]属性为class="video_scroll"的祖先节点
class_div = html.xpath('//li[2]/ancestor::*[@class="video_scroll"]')
print('li[2]class="video_scroll"的祖先节点名称:',[i.tag for i in class_div])
# 获取li[2]/a所有属性值
attributes = html.xpath('//li[2]/a/attribute::*')
print('li[2]/a的所有属性值:',attributes)
# 获取div所有子节点
div_child = html.xpath('//div/child::*')
print('div的所有子节点名称:',[i.tag for i in div_child])
# 获取body所有子孙节点
body_descendant = html.xpath('//body/descendant::*')
print('body的所有子孙节点名称:',[i.tag for i in body_descendant])
# 获取li[1]节点后的所有节点
li_following = html.xpath('//li[1]/following::*')
print('li[1]之后的所有节点名称:',[i.tag for i in li_following])
# 获取li[1]节点后的所有同级节点
li_sibling = html.xpath('//li[1]/following-sibling::*')
print('li[1]之后的所有同级节点名称:',[i.tag for i in li_sibling])
# 获取li[3]节点前的所有节点
li_preceding = html.xpath('//li[3]/preceding::*')
print('li[3]之前的所有节点名称:',[i.tag for i in li_preceding])

程序运行结果如下:

li[2]所有祖先节点名称: ['html', 'body', 'div']
li[2]指定祖先节点名称: ['body']
li[2]class="video_scroll"的祖先节点名称: ['div']
li[2]/a的所有属性值: ['javascript:', 'login(0)', 'JDK的下载']
div的所有子节点名称: ['li', 'li', 'li']
body的所有子孙节点名称: ['div', 'li', 'a', 'li', 'a', 'li', 'a']
li[1]之后的所有节点名称: ['li', 'a', 'li', 'a']
li[1]之后的所有同级节点名称: ['li', 'li']
li[3]之前的所有节点名称: ['li', 'a', 'li', 'a']

总结:
在这里插入图片描述

第二章 Beautiful Soup 模块

模块介绍请看:https://blog.csdn.net/xw1680/article/details/105845918

【示例1】使用 Beautiful Soup解析HTML代码。示例如下:

from bs4 import BeautifulSoup  # 导入BeautifulSoup库

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
<title>第一个 HTML 页面</title>
</head>
<body>
<p>body 元素的内容会显示在浏览器中。</p>
<p>title 元素的内容会显示在浏览器的标题栏中。</p>
</body>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print(soup)                  # 打印解析的HTML代码
print(type(soup))            # 打印数据类型
# 如果将html格式字符串的代码保存在 demo.html 文件中,可以通过打开HTML文件的方式进行代码的解析,
# 并且可以通过prettify()方法进行代码的格式化处理,代码如下:
# soup = BeautifulSoup(open("demo.html", encoding="utf8"), features="lxml")
# print(soup.prettify())

程序运行结果如下:

<html>
<head>
<title>第一个 HTML 页面</title>
</head>
<body>
<p>body 元素的内容会显示在浏览器中。</p>
<p>title 元素的内容会显示在浏览器的标题栏中。</p>
</body>
</html>

<class 'bs4.BeautifulSoup'>
<!DOCTYPE html>
<html lang="en">
 <head>
  <meta charset="utf-8"/>
  <title>
   lxml模块读取本地html文件测试
  </title>
 </head>
 <body>
  hello, lxml!
 </body>
</html>

【示例2】使用 Beautiful Soup 模块获取节点对应的代码。示例如下:

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
<title>第一个 HTML 页面</title>
</head>
<body>
<p>body 元素的内容会显示在浏览器中。</p>
<p>title 元素的内容会显示在浏览器的标题栏中。</p>
</body>
</html>
"""

# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print('head节点内容为:\n',soup.head)               # 打印head节点
print('body节点内容为:\n',soup.body)               # 打印body节点
print('title节点内容为:\n',soup.title)              # 打印title节点
print('p节点内容为:\n',soup.p)                  # 打印p节点
"""
在打印p节点对应的代码时,可以发现只打印了第一个p节点内容,这说明当有多个节点时,该选择方式只会获取第一个节点中的内容
其他后面的节点将被忽略。
"""
#获取节点名称
print(soup.head. name)
print( soup.body . name)
print(soup.title.name)
print(soup.p.name)

程序运行结果如下:

head节点内容为:
 <head>
<title>第一个 HTML 页面</title>
</head>
body节点内容为:
 <body>
<p>body 元素的内容会显示在浏览器中。</p>
<p>title 元素的内容会显示在浏览器的标题栏中。</p>
</body>
title节点内容为:
 <title>第一个 HTML 页面</title>
p节点内容为:
 <p>body 元素的内容会显示在浏览器中。</p>
head
body
title
p

【示例3】获取节点属性。示例如下:

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>横排响应式登录</title>
    <meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
    <meta name="viewport" content="width=device-width"/>
    <link href="font/css/bootstrap.min.css" type="text/css" rel="stylesheet">
    <link href="css/style.css" type="text/css" rel="stylesheet">
</head>
<body>
<h3>登录</h3>
<div class="glyphicon glyphicon-envelope"><input type="text" placeholder="请输入邮箱"></div>
<div class="glyphicon glyphicon-lock"><input type="password" placeholder="请输入密码"></div>
</body>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print('meta节点中属性如下:\n',soup.meta.attrs)
print('link节点中属性如下:\n',soup.link.attrs)
print('div节点中属性如下:\n',soup.div.attrs)
print('-------------------------------分割线-------------------------------')
# 在attrs后面添加括号并在括号内添加属性名称即可获取指定属性对应的值。
print ( 'meta节点中http-equiv属性对应的值为: ',soup.meta.attrs[ 'http-equiv'])
print( 'link节点中href属性对应的值为: ',soup.link.attrs [ 'href'])
print('div节点中class属性对应的值为: ',soup.div.attrs['class'])
print('-------------------------------分割线-------------------------------')
# 在获取节点中指定属性所对应的值时,除了使用上面的方式以外,还可以不写attrs,
# 直接在节点后面以中括号的形式直接添加属性名称,来获取对应的值。代码如下:
print( 'meta节点中http-equiv属性对应的值为: ', soup.meta[ 'http-equiv'])
print('link节点中href属性对应的值为: ',soup.link[ 'href'])
print('div节点中class属性对应的值为: ',soup.div['class'])

程序运行结果如下:

meta节点中属性如下:
 {'http-equiv': 'Content-Type', 'content': 'text/html', 'charset': 'utf-8'}
link节点中属性如下:
 {'href': 'font/css/bootstrap.min.css', 'type': 'text/css', 'rel': ['stylesheet']}
div节点中属性如下:
 {'class': ['glyphicon', 'glyphicon-envelope']}
-------------------------------分割线-------------------------------
meta节点中http-equiv属性对应的值为:  Content-Type
link节点中href属性对应的值为:  font/css/bootstrap.min.css
div节点中class属性对应的值为:  ['glyphicon', 'glyphicon-envelope']
-------------------------------分割线-------------------------------
meta节点中http-equiv属性对应的值为:  Content-Type
link节点中href属性对应的值为:  font/css/bootstrap.min.css
div节点中class属性对应的值为:  ['glyphicon', 'glyphicon-envelope']

【示例4】获取节点所包含的文本内容。示例如下:

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>横排响应式登录</title>
    <meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
    <meta name="viewport" content="width=device-width"/>
    <link href="font/css/bootstrap.min.css" type="text/css" rel="stylesheet">
    <link href="css/style.css" type="text/css" rel="stylesheet">
</head>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print('head节点内容如下:\n',soup.head)
print('head节点数据类型为:',type(soup.head))
print('head节点中title节点内容如下:\n',soup.head.title)
print('head节点中title节点数据类型为:',type(soup.head.title))
print('head节点中title节点中的文本内容为:',soup.head.title.string)
print('head节点中title节点中文本内容的数据类型为:',type(soup.head.title.string))

程序运行结果如下:

head节点内容如下:
 <head>
<title>横排响应式登录</title>
<meta charset="utf-8" content="text/html" http-equiv="Content-Type"/>
<meta content="width=device-width" name="viewport"/>
<link href="font/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
<link href="css/style.css" rel="stylesheet" type="text/css"/>
</head>
head节点数据类型为: <class 'bs4.element.Tag'>
head节点中title节点内容如下:
 <title>横排响应式登录</title>
head节点中title节点数据类型为: <class 'bs4.element.Tag'>
head节点中title节点中的文本内容为: 横排响应式登录
head节点中title节点中文本内容的数据类型为: <class 'bs4.element.NavigableString'>

【示例5】实现获取某节点下所有子节点内容。示例如下:

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>关联获取演示</title>
    <meta charset="utf-8"/>
</head>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.head.contents)           # 列表形式打印head下所有子节点
# 通过 head.contents 所获取的所有子节点中有三个换行符\n以及两个子标题(title 与meta)对应的所有内容。
print(soup.head.children)           # 可迭代对象形式打印head下所有子节点
print( list(soup.head.children ))
#打印将可迭代对象转换为列表形式的所有子节点
# head.children所获取的则是一个“list_iterator ”可迭代对象,如果需要获取该对象中的所有内容可以直接将其转换为list类型或者
# 通过 for循环遍历的方式进行获取。代码如下:
for i in soup.head.children:
#循环遍历可迭代对象中的所有子节点
    print(i)

程序运行结果如下:

['\n', <title>关联获取演示</title>, '\n', <meta charset="utf-8"/>, '\n']
<list_iterator object at 0x0000020AEE4B18C8>
['\n', <title>关联获取演示</title>, '\n', <meta charset="utf-8"/>, '\n']


<title>关联获取演示</title>


<meta charset="utf-8"/>


【示例6】使用descendants属性获取子孙节点内容。示例如下:

# 创建模拟HTML代码的字符串
html_doc = """
<html>
…此处省略…
<body>
<div id="test1">
    <div id="test2">
        <ul>
            <li class="test3" value = "user1234">
                此处为演示信息
            </li>
        </ul>
    </div>
</div>
</body>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.body.descendants)          # 打印body节点下所有子孙节点内容的generator对象
for i in soup.body.descendants:       # 循环遍历generator对象中的所有子孙节点
    print(i)                            # 打印子孙节点内容

程序运行结果如下:

<generator object Tag.descendants at 0x0000020AEE32F548>
<p>
…此处省略…
</p>

…此处省略…



<div id="test1">
<div id="test2">
<ul>
<li class="test3" value="user1234">
                此处为演示信息
            </li>
</ul>
</div>
</div>


<div id="test2">
<ul>
<li class="test3" value="user1234">
                此处为演示信息
            </li>
</ul>
</div>


<ul>
<li class="test3" value="user1234">
                此处为演示信息
            </li>
</ul>


<li class="test3" value="user1234">
                此处为演示信息
            </li>

                此处为演示信息
            








【示例7】获取父节点及祖先节点内容。示例如下:

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>关联获取演示</title>
    <meta charset="utf-8"/>
</head>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.title.parent)                # 打印title节点的父节点内容
print(soup.title.parents)               # 打印title节点的父节点及以上内容的generator对象
for i in soup.title.parents:           # 循环遍历generator对象中的所有父

程序运行结果如下:

<head>
<title>关联获取演示</title>
<meta charset="utf-8"/>
</head>
<generator object PageElement.parents at 0x0000020AEE32F548>
head
html
[document]

【示例8】获取兄弟节点。示例如下:

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>关联获取演示</title>
    <meta charset="utf-8"/>
</head>
<body>
<p class="p-1" value = "1"><a href="https://blog.csdn.net/xw1680/article/details/119493481">Flume 从0到高手一站式养成记</a></p>
第一个p节点下文本
<div class="div-1" value = "2"><a href="https://blog.csdn.net/xw1680/article/details/119363781">消息队列之Kafka从入门到小牛</a></div>
<p class="p-3" value = "3"><a href="https://blog.csdn.net/xw1680/article/details/119004640">万字文肝Redis基础知识</a></p>
<div class="div-2" value = "4"><a href="https://blog.csdn.net/xw1680/article/details/118743183">3天极速掌握 Scala 语言:First Day</a></div>
</body>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.p.next_sibling)               # 打印第一个p节点下一个兄弟节点(文本节点内容)
print(list(soup.p.next_sibling))         # 以列表形式打印文本节点中的所有元素
div = soup.p.next_sibling.next_sibling  # 获取p节点同级的第一个div节点
print(div)                               # 打印第一个div节点内容
print(div.previous_sibling)              # 打印第一个div节点上一个兄弟节点(文本节点内容)
print('获取p节点后面的所有兄弟节点如下: \n',list(soup.p.next_siblings))
print('获取p节点前面的所有兄弟节点如下: \n',list(soup.p.previous_siblings))

程序运行结果如下:

第一个p节点下文本

['\n', '第', '一', '个', 'p', '节', '点', '下', '文', '本', '\n']
<div class="div-1" value="2"><a href="https://blog.csdn.net/xw1680/article/details/119363781">消息队列之Kafka从入门到小牛</a></div>

第一个p节点下文本

获取p节点后面的所有兄弟节点如下: 
 ['\n第一个p节点下文本\n', <div class="div-1" value="2"><a href="https://blog.csdn.net/xw1680/article/details/119363781">消息队列之Kafka从入门到小牛</a></div>, '\n', <p class="p-3" value="3"><a href="https://blog.csdn.net/xw1680/article/details/119004640">万字文肝Redis基础知识</a></p>, '\n', <div class="div-2" value="4"><a href="https://blog.csdn.net/xw1680/article/details/118743183">3天极速掌握 Scala 语言:First Day</a></div>, '\n']
获取p节点前面的所有兄弟节点如下: 
 ['\n']

【示例9】find_all(name)通过节点名称获取内容。示例如下:

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>关联获取演示</title>
    <meta charset="utf-8"/>
</head>

<body>
<p class="p-1" value = "1"><a href="https://blog.csdn.net/xw1680/article/details/119493481">Flume 从0到高手一站式养成记</a></p>
<p class="p-2" value = "2"><a href="https://blog.csdn.net/xw1680/article/details/119363781">消息队列之Kafka从入门到小牛</a>></p>
<p class="p-3" value = "3"><a href="https://blog.csdn.net/xw1680/article/details/119004640">万字文肝Redis基础知识</a></p>
<div class="div-2" value = "4"><a href="https://blog.csdn.net/xw1680/article/details/118743183">3天极速掌握 Scala 语言:First Day</a></div>
</body>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.find_all(name='p'))           # 打印名称为p的所有节点内容
print(type(soup.find_all(name='p')))     # 打印数据类型
print(soup.find_all(name='p')[0])
print(type(soup.find_all(name='p')[0])) # 打印数据类型
print( soup.find_all(name='p')[0].find_all(name='a')) # 打印第一个p节点内的子节点a

程序运行结果如下:

[<p class="p-1" value="1"><a href="https://blog.csdn.net/xw1680/article/details/119493481">Flume 从0到高手一站式养成记</a></p>, <p class="p-2" value="2"><a href="https://blog.csdn.net/xw1680/article/details/119363781">消息队列之Kafka从入门到小牛</a>&gt;</p>, <p class="p-3" value="3"><a href="https://blog.csdn.net/xw1680/article/details/119004640">万字文肝Redis基础知识</a></p>]
<class 'bs4.element.ResultSet'>
<p class="p-1" value="1"><a href="https://blog.csdn.net/xw1680/article/details/119493481">Flume 从0到高手一站式养成记</a></p>
<class 'bs4.element.Tag'>
[<a href="https://blog.csdn.net/xw1680/article/details/119493481">Flume 从0到高手一站式养成记</a>]

【示例10】find_all(attrs)通过指定属性获取内容。示例如下:

# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>关联获取演示</title>
    <meta charset="utf-8"/>
</head>

<body>
<p class="p-1" value = "1"><a href="https://blog.csdn.net/xw1680/article/details/119493481">Flume 从0到高手一站式养成记</a></p>
<p class="p-2" value = "2"><a href="https://blog.csdn.net/xw1680/article/details/119363781">消息队列之Kafka从入门到小牛</a>></p>
<p class="p-3" value = "3"><a href="https://blog.csdn.net/xw1680/article/details/119004640">万字文肝Redis基础知识</a></p>
<div class="div-2" value = "4"><a href="https://blog.csdn.net/xw1680/article/details/118743183">3天极速掌握 Scala 语言:First Day</a></div>
</body>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print('字典参数结果如下:')
print(soup.find_all(attrs={'value':'1'}))        # 打印value值为1的所有内容,字典参数
print('赋值参数结果如下:')
print(soup.find_all(class_='p-1'))               # 打印class为p-1的所有内容,赋值参数
print(soup.find_all(value='3'))                  # 打印value值为3的所有内容,赋值参数

程序运行结果如下:

字典参数结果如下:
[<p class="p-1" value="1"><a href="https://blog.csdn.net/xw1680/article/details/119493481">Flume 从0到高手一站式养成记</a></p>]
赋值参数结果如下:
[<p class="p-1" value="1"><a href="https://blog.csdn.net/xw1680/article/details/119493481">Flume 从0到高手一站式养成记</a></p>]
[<p class="p-3" value="3"><a href="https://blog.csdn.net/xw1680/article/details/119004640">万字文肝Redis基础知识</a></p>]

【示例11】find_all(text)获取节点中的文本。示例如下:

import re                      # 导入正则表达式模块
# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>关联获取演示</title>
    <meta charset="utf-8"/>
</head>

<body>
<p class="p-1" value = "1"><a href="https://blog.csdn.net/xw1680/article/details/119493481">Flume 从0到高手一站式养成记</a></p>
<p class="p-2" value = "2"><a href="https://blog.csdn.net/xw1680/article/details/119363781">消息队列之Kafka从入门到小牛</a>></p>
<p class="p-3" value = "3"><a href="https://blog.csdn.net/xw1680/article/details/119004640">万字文肝Redis基础知识</a></p>
<div class="div-2" value = "4"><a href="https://blog.csdn.net/xw1680/article/details/118743183">3天极速掌握 Scala 语言:First Day</a></div>
</body>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print('指定字符串所获取的内容如下:')
print(soup.find_all(text='消息队列之Kafka从入门到小牛'))         # 打印指定字符串所获取的内容
print('指定正则表达式对象所获取的内容如下:')
print(soup.find_all(text=re.compile(r'消息')))    # 打印指定正则表达式对象所获取的内容

程序运行结果如下:

指定字符串所获取的内容如下:
['消息队列之Kafka从入门到小牛']
指定正则表达式对象所获取的内容如下:
['消息队列之Kafka从入门到小牛']

【示例12】find()方法获取第一个匹配的节点内容。示例如下:

import re                      # 导入正则表达式模块
# 创建模拟HTML代码的字符串
# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>关联获取演示</title>
    <meta charset="utf-8"/>
</head>

<body>
<p class="p-1" value = "1"><a href="https://blog.csdn.net/xw1680/article/details/119493481">Flume 从0到高手一站式养成记</a></p>
<p class="p-2" value = "2"><a href="https://blog.csdn.net/xw1680/article/details/119363781">消息队列之Kafka从入门到小牛</a>></p>
<p class="p-3" value = "3"><a href="https://blog.csdn.net/xw1680/article/details/119004640">万字文肝Redis基础知识</a></p>
<div class="div-2" value = "4"><a href="https://blog.csdn.net/xw1680/article/details/118743183">3天极速掌握 Scala 语言:First Day</a></div>
</body>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.find(name='p'))                  # 打印第一个name为p的节点内容
print(soup.find(class_='p-3'))              # 打印第一个class为p-3的节点内容
print(soup.find(attrs={'value':'4'}))       # 打印第一个value为4的节点内容
print(soup.find(text=re.compile('语言'))) # 打印第一个文本中包含语言的文本信息

程序运行结果如下:

<p class="p-1" value="1"><a href="https://blog.csdn.net/xw1680/article/details/119493481">Flume 从0到高手一站式养成记</a></p>
<p class="p-3" value="3"><a href="https://blog.csdn.net/xw1680/article/details/119004640">万字文肝Redis基础知识</a></p>
<div class="div-2" value="4"><a href="https://blog.csdn.net/xw1680/article/details/118743183">3天极速掌握 Scala 语言:First Day</a></div>
3天极速掌握 Scala 语言:First Day

除了 find_all() 和 find() 方法可以实现按照指定条件获取节点内容以外,Beautiful Soup 模块还提供了多个其他方法,这些方法的使用方式与 find_all() 和 find() 方法相同,只是查询的范围不同,各个方法的具体说明可以查看官网:https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/#id27

【示例13】使用CSS选择器获取节点内容。示例如下:

CSS 选择器参考手册:https://www.w3school.com.cn/cssref/css_selectors.asp

from bs4 import BeautifulSoup  # 导入BeautifulSoup库
# 创建模拟HTML代码的字符串
html_doc = """
<html>
<head>
    <title>关联获取演示</title>
    <meta charset="utf-8"/>
</head>
<body>
    <div class="test_1" id="class_1"> 
        <p class="p-1" value = "1"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180293.htm">1</a></p>
        <p class="p-2" value = "2"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180275.htm">2</a></p>
        <p class="p-3" value = "3"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180220.htm">3</a></p>
        <p class="p-4" value = "4"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180198.htm">4</a></p>
    </div>
    <div class="test_2" id="class_2">
        <p class="p-5"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180107.htm">5</a></p>
        <p class="p-6"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180051.htm">6</a></p>
        <p class="p-7"><a href="http://news.youth.cn/jsxw/202108/t20210821_13179990.htm">7</a></p>
    </div>    
</body>
</html>
"""
# 创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features="lxml")
print('所有p节点内容如下:')
print(soup.select('p'))                # 打印所有p节点内容
print('所有p节点中的第二个p节点内容如下:')
print(soup.select('p')[1])             # 打印所有p节点中的第二个p节点
print('逐层获取的title节点如下:')
print(soup.select('html head title'))  # 打印逐层获取的title节点
print('类名为test_2所对应的节点如下:')
print(soup.select('.test_2'))          # 打印类名为test_2所对应的节点
print('id值为class_1所对应的节点如下:')
print(soup.select('#class_1'))         # 打印id值为class_1所对应的节点

程序运行结果如下:

所有p节点内容如下:
[<p class="p-1" value="1"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180293.htm">1</a></p>, <p class="p-2" value="2"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180275.htm">2</a></p>, <p class="p-3" value="3"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180220.htm">3</a></p>, <p class="p-4" value="4"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180198.htm">4</a></p>, <p class="p-5"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180107.htm">5</a></p>, <p class="p-6"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180051.htm">6</a></p>, <p class="p-7"><a href="http://news.youth.cn/jsxw/202108/t20210821_13179990.htm">7</a></p>]
所有p节点中的第二个p节点内容如下:
<p class="p-2" value="2"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180275.htm">2</a></p>
逐层获取的title节点如下:
[<title>关联获取演示</title>]
类名为test_2所对应的节点如下:
[<div class="test_2" id="class_2">
<p class="p-5"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180107.htm">5</a></p>
<p class="p-6"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180051.htm">6</a></p>
<p class="p-7"><a href="http://news.youth.cn/jsxw/202108/t20210821_13179990.htm">7</a></p>
</div>]
id值为class_1所对应的节点如下:
[<div class="test_1" id="class_1">
<p class="p-1" value="1"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180293.htm">1</a></p>
<p class="p-2" value="2"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180275.htm">2</a></p>
<p class="p-3" value="3"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180220.htm">3</a></p>
<p class="p-4" value="4"><a href="http://news.youth.cn/jsxw/202108/t20210821_13180198.htm">4</a></p>
</div>]

总结:
在这里插入图片描述
笔者在这里声明,笔者写文章只是为了学习交流,以及让更多学习 Python 基础的读者少走一些弯路以及方便笔者自己复习时查看,节省时间,并不用做其他用途,如有侵权,联系博主删除即可。感谢您阅读本篇博文,希望本文能成为您编程路上的领航者。祝您阅读愉快!


在这里插入图片描述

????好书不厌读百回,熟读课思子自知。而我想要成为全场最靓的仔,就必须坚持通过学习来获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。
????如果我的博客对你有帮助、如果你喜欢我的博客内容,请 点赞评论收藏 一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。
?编码不易,大家的支持就是我坚持下去的动力。点赞后不要忘了 关注 我哦!

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-08-23 16:38:21  更:2021-08-23 16:38:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 11:45:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计