第一章 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
parser = etree.HTMLParser()
html = etree.parse('demo.html', parser=parser)
print(type(html))
html_txt = etree.tostring(html, encoding="utf-8")
print(html_txt.decode('utf-8'))
【示例2】解析字符串类型的 HTML 代码。etree 子模块还提供了一个 HTML() 方法,该方法可以实现解析字符串类型的 HTML 代码。示例代码如下:
from lxml import etree
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_txt = etree.tostring(html, encoding="utf-8")
print(html_txt.decode('utf-8'))
【示例3】解析服务器返回的 HTML 代码。在实际开发中,HTML() 方法的使用率是非常高的,因为发送网络请求后,多数情况下都会将返回的响应结果转换为字符串类型,如果返回的结果是 HTML 代码,则需要使用 HTML() 方法来进行解析。示例代码如下:
from lxml import etree
import requests
from requests.auth import HTTPBasicAuth
url = 'http://sck.rjkflm.com:666/spider/auth/'
ah = HTTPBasicAuth('admin', 'admin')
response = requests.get(url=url, auth=ah)
if response.status_code == 200:
html = etree.HTML(response.text)
html_txt = etree.tostring(html, encoding="utf-8")
print(html_txt.decode('utf-8'))
"""
分析: 运行结果中会出现 表示 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)
node_all = html.xpath('//*')
print('数据类型:', type(node_all))
print('数据长度:', len(node_all))
print('数据内容:', node_all)
print('节点名称:', [i.tag for i in node_all])
html = etree.HTML(html_str)
li_all = html.xpath('//li')
print('所有li节点', li_all)
print('获取指定li节点:', li_all[1])
li_txt = etree.tostring(li_all[1], encoding="utf-8")
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_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)
a_all = html.xpath('//li/a')
print('所有子节点a', a_all)
print('获取指定a节点:', a_all[1])
a_txt = etree.tostring(a_all[1], encoding="utf-8")
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_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)
a_all = html.xpath('//ul//a')
print('所有子节点a',a_all)
print('获取指定a节点:',a_all[4])
a_txt = etree.tostring(a_all[4],encoding = "utf-8")
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_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)
a_all_parent = html.xpath('//a/..')
print('所有a的父节点',a_all_parent)
print('获取指定a的父节点:',a_all_parent[0])
a_txt = etree.tostring(a_all_parent[0],encoding = "utf-8")
print('获取指定节点HTML代码:\n',a_txt.decode('utf-8'))
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_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)
a_text = html.xpath('//a/text()')
print('所有a节点中文本信息:',a_text)
程序运行结果如下:
所有a节点中文本信息: ['什么是Java', 'Java的版本']
【示例9】使用[@…] 实现节点属性的匹配,示例如下:
html_str = '''
<div class="video_scroll">
<div class="level">什么是Java</div>
<div class="level">Java的版本</div>
</div>
'''
html = etree.HTML(html_str)
div_one = html.xpath('//div[@class="level"]/text()')
print(div_one)
程序运行结果如下:
['什么是Java', 'Java的版本']
【示例10】属性多值匹配进行节点内容的筛选,示例如下:
html_str = '''
<div class="video_scroll">
<div class="level one">什么是Java</div>
<div class="level">Java的版本</div>
</div>
'''
html = etree.HTML(html_str)
div_one = html.xpath('//div[@class="level one"]/text()')
print(div_one)
html = etree.HTML(html_str)
div_all = html.xpath('//div[contains(@class,"level")]/text()')
print(div_all)
程序运行结果如下:
['什么是Java']
['什么是Java', 'Java的版本']
【示例11】一个节点中多个属性的匹配,示例如下:
html_str = '''
<div class="video_scroll">
<div class="level" id="one">什么是Java</div>
<div class="level">Java的版本</div>
</div>
'''
html = etree.HTML(html_str)
div_all = html.xpath('//div[@class="level" and @id="one"]/text()')
print(div_all)
程序运行结果如下:
['什么是Java']
【示例12】使用 @获取属性所对应的值,示例如下:
html_str = '''
<div class="video_scroll">
<li class="level" id="one">什么是Java</li>
</div>
'''
html = etree.HTML(html_str)
li_class = html.xpath('//div/li/@class')
li_id = html.xpath('//div/li/@id')
print('class属性值:',li_class)
print('id属性值:',li_id)
程序运行结果如下:
class属性值: ['level']
id属性值: ['one']
【示例13】使用索引按序获取属性对应的值,示例如下:
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)
li_all = html.xpath('//div/li/a/@title')
print('所有属性值:',li_all)
li_first = html.xpath('//div/li[1]/a/@title')
print('第一个属性值:',li_first)
li_four = html.xpath('//div/li[4]/a/@title')
print('第四个属性值:',li_four)
html = etree.HTML(html_str)
li_last = html.xpath('//div/li[last()]/a/@title')
print('最后一个属性值:',li_last)
li = html.xpath('//div/li[position()=1]/a/@title')
print('第一个位置的属性值:',li)
li = html.xpath('//div/li[last()-1]/a/@title')
print('倒数第二个位置的属性值:',li)
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_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)
ancestors = html.xpath('//li[2]/ancestor::*')
print('li[2]所有祖先节点名称:',[i.tag for i in ancestors])
body = html.xpath('//li[2]/ancestor::body')
print('li[2]指定祖先节点名称:',[i.tag for i in body])
class_div = html.xpath('//li[2]/ancestor::*[@class="video_scroll"]')
print('li[2]class="video_scroll"的祖先节点名称:',[i.tag for i in class_div])
attributes = html.xpath('//li[2]/a/attribute::*')
print('li[2]/a的所有属性值:',attributes)
div_child = html.xpath('//div/child::*')
print('div的所有子节点名称:',[i.tag for i in div_child])
body_descendant = html.xpath('//body/descendant::*')
print('body的所有子孙节点名称:',[i.tag for i in body_descendant])
li_following = html.xpath('//li[1]/following::*')
print('li[1]之后的所有节点名称:',[i.tag for i in li_following])
li_sibling = html.xpath('//li[1]/following-sibling::*')
print('li[1]之后的所有同级节点名称:',[i.tag for i in li_sibling])
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
html_doc = """
<html>
<head>
<title>第一个 HTML 页面</title>
</head>
<body>
<p>body 元素的内容会显示在浏览器中。</p>
<p>title 元素的内容会显示在浏览器的标题栏中。</p>
</body>
</html>
"""
soup = BeautifulSoup(html_doc, features="lxml")
print(soup)
print(type(soup))
程序运行结果如下:
<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_doc = """
<html>
<head>
<title>第一个 HTML 页面</title>
</head>
<body>
<p>body 元素的内容会显示在浏览器中。</p>
<p>title 元素的内容会显示在浏览器的标题栏中。</p>
</body>
</html>
"""
soup = BeautifulSoup(html_doc, features="lxml")
print('head节点内容为:\n',soup.head)
print('body节点内容为:\n',soup.body)
print('title节点内容为:\n',soup.title)
print('p节点内容为:\n',soup.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_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>
"""
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('-------------------------------分割线-------------------------------')
print ( 'meta节点中http-equiv属性对应的值为: ',soup.meta.attrs[ 'http-equiv'])
print( 'link节点中href属性对应的值为: ',soup.link.attrs [ 'href'])
print('div节点中class属性对应的值为: ',soup.div.attrs['class'])
print('-------------------------------分割线-------------------------------')
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_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>
"""
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_doc = """
<html>
<head>
<title>关联获取演示</title>
<meta charset="utf-8"/>
</head>
</html>
"""
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.head.contents)
print(soup.head.children)
print( list(soup.head.children ))
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_doc = """
<html>
…此处省略…
<body>
<div id="test1">
<div id="test2">
<ul>
<li class="test3" value = "user1234">
此处为演示信息
</li>
</ul>
</div>
</div>
</body>
</html>
"""
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.body.descendants)
for i in soup.body.descendants:
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_doc = """
<html>
<head>
<title>关联获取演示</title>
<meta charset="utf-8"/>
</head>
</html>
"""
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.title.parent)
print(soup.title.parents)
for i in soup.title.parents:
程序运行结果如下:
<head>
<title>关联获取演示</title>
<meta charset="utf-8"/>
</head>
<generator object PageElement.parents at 0x0000020AEE32F548>
head
html
[document]
【示例8】获取兄弟节点。示例如下:
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>
"""
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.p.next_sibling)
print(list(soup.p.next_sibling))
div = soup.p.next_sibling.next_sibling
print(div)
print(div.previous_sibling)
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_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>
"""
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.find_all(name='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 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>]
<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_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>
"""
soup = BeautifulSoup(html_doc, features="lxml")
print('字典参数结果如下:')
print(soup.find_all(attrs={'value':'1'}))
print('赋值参数结果如下:')
print(soup.find_all(class_='p-1'))
print(soup.find_all(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_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>
"""
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_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>
"""
soup = BeautifulSoup(html_doc, features="lxml")
print(soup.find(name='p'))
print(soup.find(class_='p-3'))
print(soup.find(attrs={'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
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>
"""
soup = BeautifulSoup(html_doc, features="lxml")
print('所有p节点内容如下:')
print(soup.select('p'))
print('所有p节点中的第二个p节点内容如下:')
print(soup.select('p')[1])
print('逐层获取的title节点如下:')
print(soup.select('html head title'))
print('类名为test_2所对应的节点如下:')
print(soup.select('.test_2'))
print('id值为class_1所对应的节点如下:')
print(soup.select('#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 基础的读者少走一些弯路以及方便笔者自己复习时查看,节省时间,并不用做其他用途,如有侵权,联系博主删除即可。感谢您阅读本篇博文,希望本文能成为您编程路上的领航者。祝您阅读愉快!
????好书不厌读百回,熟读课思子自知。而我想要成为全场最靓的仔,就必须坚持通过学习来获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。 ????如果我的博客对你有帮助、如果你喜欢我的博客内容,请 点赞 、评论 、收藏 一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。 ?编码不易,大家的支持就是我坚持下去的动力。点赞后不要忘了 关注 我哦!
|