Python中xPath技术和BeautifulSoup的使用
xpath基本知识
XPath语法:使用路径表达式来选取XML或HTML文档中的节点或节点集
路径表达式
nodename:表示选取此节点的所有子节点
/ : 表示从根节点选取
// :选择任意位置的某个节点。
. :选取当前节点
.. :选取当前节点的父节点
@ :选取属性
谓语实例
实现效果 路劲表达式
选取属于classroom子元素的第一个student元素 /classroom/student[1]
选取属于classroom子元素的最后一个student元素 /classroom/student[last()]
选取属于classroom子元素的倒数第二个stduent元素 /classroom/stduent[last()-1]
选取最前面的两个属于classroom元素的子元素的student元素 /classroom/stduent[position()<3]
选取所有拥有名为lang的属性的name元素 //name[@lang]
选取所有name元素,且这些元素拥有值为eng的lang属性 //name[@lang='en']
选取classroom元素的所有student元素,且其中的age元素的值须大于20 .classroom.stduent[age>20]
选取classroom元素中的student元素的所有name元素,且其中的age元素的值须大于20 /classroom/stduent[age>20]/name
通配符“*”与“|”操作
实现效果 路径表达式
选取classroom元素的所有子元素 /classroom/*
选取文档中的所有元素 //*
选取所有带有属性的name元素 //name[@*]
选取stduent元素的所有name和age元素 //stduent/name | //stduent/age
选取属于classroom元素的student元素的所有name元素,以及文档中所有的age元素 /classroom/stduent/name | //age
XPath轴 步的语法为 轴名称:节点测试[谓语]
轴名称 含义
child 选取当前节点的所有子节点
parent 选取当前节点的父节点
ancestor 选取当前节点的所有先辈(父、祖父等)
ancestor-or-self 选取当前节点的所有先辈以及当前节点本身
descendant 选取当前节点的所有后代节点
descendant-or-self 选取当前节点的所有后代节点以及当前节点本身
preceding 选取文档中当前节点的开始标记之前的所有节点
following 选取文档中当前节点的结束标记之后的所有节点
preceding-sibling 选取当前节点之前的所有同级节点
following-sibling 选取当前节点之后的所用同级节点
self 选取当前节点
attribute 选取当前节点的所有属性
namespace 选取当前节点的所有命名空间
XPath轴示例分析
实现效果 路径表达式
选取当前classroom节点中子元素的teacher节点 /classroom/child::teacher
选取所有id节点的父节点 //id/parent::*
选取所有以classid为子节点的祖先节点 //classid/ancestor::*
选取classroom节点下的所有后代节点 /classroom/descendant::*
选取所有以student为父节点的id元素 //student/descendant::id
选取所有classid元素的祖先节点及本身 //classid/ancestor-or-self::*
选择/classroom/student本身及其所有后代元素 /classroom/student/descendant-or-self::*
选取/classroom/teacher之前的所有同级节点,结果就是选所有的student节点 /classroom/teacher/preceding-sibling::*
选取/classroom中第二个stduent之后的所有同级节点 /classroom/student[2]/following-sibling::*
选取/classroom/teacher节点所有之前的节点(除其祖先外),不仅仅是student节点,还有里面的子节点 /classroom/teacher/preceding::*
选取/classroom中第二个student之后的所有节点,结果就是选择了teacher节点及其子节点 /classroom/student[2]/following::*
选取student节点,单独使用没有什么意思 //stduent/self::*
选取/classroom/teacher/name节点下的所有属性 /classroom/teacher/name/attribute::*
XPath运算符示例分析
含义 实例
选取classroom元素的所有student元素 /classroom/student[age=19+1] /classroom/stduent[age=5*4] /classroom/student[age=21-1]
且其中的age元素的值须等于20 /classroom/student[age=40div2]
类似可以选取 大于、小于、不等于等操作
or 运算实例 /classroom/stduent[age<20 or age>25] .................age小于20或者大于25
and 运算实例 /classroom/stduent[age>20 and age<25] ..................age在20 到25 之间
mod 计算除法的余数
实例代码
from lxml import etreecontentStream = open(r'xpathText.xml', 'rb') content = contentStream.read().decode('utf-8') root = etree.XML(content) print(content) print('-------') em = root.xpath('/classroom/student[2]/following::*') print(em[0].xpath('./name/text()'))#获取name标签中文本的内容 print(em[0].xpath('./name/@lang')) #获取name标签中属性名为lang的属性值
BeautifulSoup基础知识
创建BeautifulSoup对象的两种方式 1.通过字符串创建 soup=BeautifulSoup(htl_str,'lxml') 其中'lxml'表示指定的解析方式
2.通过文件创建 soup=BeautifulSoup(open('index.html'))
对象种类 四种 Tag、NavigableString、BeautifulSoup 、Comment
1)Tag
在html中每个标签及其里面的内容就是一个Tag对象,如何抽取Tag呢?
soup.title抽取title soup.a 抽取a 利用soup+标记名查找的是再内容中第一个符合要求的标记
Tag中有两个最重要的属性:name和attributes.每个Tag都有自己的名字,通过.name来获取
修改Tag的name,修改完成后将影响所有通过当前Beautiful Soup对象生成的HTML文档
html_str = """<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></body></html>"""soup = BeautifulSoup(html_str, 'lxml') # soup = BeautifulSoup(open(r'index.html','rb'),'lxml') print(soup.prettify()) #以格式化的形式输出文档的内容 print(soup.name) print(soup.title.name)#输出title的名称 soup.title.name = 'mytitle' #修改title的名称为mytitle print(soup.title) #title已经修改输出None print(soup.mytitle)#输出mytitle Tag
输出结果
整个文档的内容 [document] title None <mytitle>The Dormouse's story</mytitle>
获取Tag属性?<p class="title"><b>The Dormouse's story</b></p>Tag p中有一个属性class值为title,获取代码如下:
Tag属性值的修改类似于上述标签名的修改 soup.p['class']='myclass' 就把属性值title改为了myclass
# 获取Tag中的属性 和字典类似 print(soup.p['class']) print(soup.p.get('class'))
输出结果
['title'] ['title']
用于获取Tag所有属性的方法 print(soup.p.attrs)以字典的行书获取指定Tag的所有属性:属性值字典
输出格式如下
{'class': ['title']}
2)NavigableString 当已经得到了标记的内容,要想获取标记的内部文字怎么办呢?需要用到.string。
print(soup.b.string)#输出Tag对象b的内容 print(type(soup.b.string))#输出Tage对象b的内容的类型 其实就是NavigableString类型
输出结果
The Dormouse's story <class 'bs4.element.NavigableString'>
3)Beautiful Soup
Beautiful Soup对象表示的是一个文档的全部内容。大部分时候,可以把它当作Tag对象,是一个特殊的人Tag,实例如下
print(type(soup.name)) print(soup.name) print(soup.attrs)
输出结果
<class 'str'> [document] {}
4) Comment 文档的注释部分 ,示例如下
print(soup.a.string) print(type(soup.a.string))
输出结果
Elsie <class 'bs4.element.Comment'>
遍历文档
1)子节点
Tag中的.contents和.children是非常重要的,都是输出直接子节点,Tag的contents属性可以将Tag子节点以列表的方式输出:
print(soup.html.contents) print(soup.html.contents[1])#如果soup.html.contents[1].string会直接输出文档里的内容,具体解释看下面
输出结果
['\n', <head><mytitle>The Dormouse's story</mytitle></head>, '\n', <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>, '\n'] <head><mytitle>The Dormouse's story</mytitle></head>
Tag中children,其实.children返回的是一个生成器,可以对Tag的子节点进行循环
for child in soup.html.children: # 孩子结点递归循环print(child)
输出结果:对于输出换行时,他要空两行,因为print自带换行
<head><mytitle>The Dormouse's story</mytitle></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>
.descendants属性可以对所有tag的子孙节点进行递归循环:head中只有一个直接2节点title,但title也包含一个子节点:字符串'The Dormouse's story',
在这种情况下,字符串也属于<head>标记的子孙节点,
for child in soup.head.descendants: # 子孙节点递归循环print(child)
输出结果
<mytitle>The Dormouse's story</mytitle> The Dormouse's story
如何获取标记的内容呢???这就涉及.string、.strings、stripped_strings三个属性
.string这个属性很有特点:如果一个标记里面没有标记了,那么.string就会返回标记里面的内容。如果标记里面只有唯一
的一个标记了,那么.string也会返回最里面的内容。如果tag包含多个子节点,tag就无法确定,string方法应该调用哪个子节点的内容,.string的输出结果是None
print(soup.head.string) print(soup.mytitle.string) print(soup.html.string)
输出结果
The Dormouse's story The Dormouse's story None
.strings属性主要应用于tag中包含多个字符串的情况,可以进行循环遍历
for stri in soup.strings:print(repr(stri))
输出结果
'\n' "The Dormouse's story" '\n' '\n' "The Dormouse's story" 'Once upon a time there were three little sisters; and their names were\n ' '\n' '\n' '\n' '\n and\n ' 'Tillie' ';\n and they lived at the bottom of a well.\n' '……' '\n' '\n'
.stripped_strings属性可以去掉输出字符串中包含的空格或换行,示例如下
for stri in soup.stripped_strings:print(repr(stri))
输出结果
"The Dormouse's story" "The Dormouse's story" 'Once upon a time there were three little sisters; and their names were' 'and' 'Tillie' ';\n and they lived at the bottom of a well.' '……'
2)父节点
每个Tag或者字符串都有父节点:被包含在某个Tag中。通过.parent可以获取某个元素的父节点
print soup.mytitle.parent 输出<head><title>........</title></head>
通过元素的.parents属性可以递归得到元素所有父辈节点,使用.parents方法遍历了<a>标记到根节点的所有节点
print(soup.a) for parent in soup.a.parents:if parent is None:print(parent)else:print(parent.name)
输出结果
<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a> p body html [document]
3)兄弟节点:可以理解为和本节点出在同一级上的节点,.next_sibling属性可以获取该节点的下一个兄弟节点,.previous_sibling则与之相反,
如果节点不存在,则返回None
可以通过.next_siblings和.previous_siblings来迭代所有的兄弟节点
4)前后节点
前后节点需要使用.next_element、previous_element这两个属性,他针对所有节点,不分层次,例如<head><title>The Dormouse‘s story</title></head>
中的下一个节点是title
如果想遍历所有的前节点或者后节点,通过.next_elements和previous_elements的迭代器就可以向前或向后访问文档的解析内容
for elem in soup.html.next_elements: #有点像深度优先遍历print(repr(elem))
输出结果
'\n' <head><mytitle>The Dormouse's story</mytitle></head> <mytitle>The Dormouse's story</mytitle> "The Dormouse's story" '\n' <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> '\n' <p class="title"><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\n ' <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a> ' Elsie ' '\n' <a class="sister" href="http://example.com/lacie" id="link2"> <!--Lacie --> </a> '\n' 'Lacie ' '\n' '\n and\n ' <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a> 'Tillie' ';\n and they lived at the bottom of a well.\n' <p class="story">……</p> '……' '\n' '\n'
搜索文档
只介绍find_all()方法,其它方法类似
函数原型
find_all(name,attrs,recursive,text,**kwargs)
1)name参数
name参数可以查找所有名字为name的标记,字符对象会被自动忽略掉。name参数取值可以是字符串、正则表达式、列表、True和方法
字符串案例 用于查找文档中所有的<b>标记 ,返回值为列表:
print(soup.find_all('b')) #输出结果 [<b>The Dormouse's story</b>]
传入正则表达式作为参数,会通过正则表达式的match()来匹配内容。下面列出所有以b开头的标记,这表示<body>和<b>标记
for tag in soup.find_all(re.compile('^b')):print(tag.name) #输出结果 body b
传入列表
print(soup.find_all(['a','b']))//找到文档中所有的<a>标记和<b>标记
传入True,True可以匹配任何值,会查找所有的tag ,但不会返回字符串节点
for tag in soup.find_all(True):print(tag.name) #输出结果 html head mytitle body p b p a a a p
如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数Tag节点,如果这个方法返回?True表示当前元素匹配并且被找到
,如果不是则返回False,比如过滤包含class属性,也包含id属性的元素
def hasClass_Id(tag):return tag.has_attr('class') and tag.has_attr('id') print(soup.find_all(hasClass_Id)) #输出结果 [<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)kwargs参数
kwargs参数就是python中的keyword参数 ,如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字Tag的属性来搜索
。搜索指定名字的属性时可以使用的参数值包括字符串、正则表达式、列表、True
传入字符串 print(soup.find_all(id='link2')) 会搜索每个tag的id属性
传入正则表达式 print(soup.find_all(href=re.compile('elsie')))搜索href属性中含有‘elsie’的tag
True print(soup.find_all(id=True)) 文档树中查找所有包含id属性的Tag,无论id的值是什么:
如果想用 class过滤·,但class是python的关键字,需要在class后main加个下划线:
soup.find_all('a',class_='sister')
有些tag属性在搜索中不能使用,比如HTML5中的data-*属性 可以通过find_all()方法的attrs参数定义一个字典参数来搜索包含特殊属性的tag
,
data_soup = BeautifulSoup('<div data-foo="value">foo!</div>', 'lxml') print(data_soup.find_all(attrs={"data-foo": "value"})) # data_soup.find_all(data - foo = 'value') #报错 特殊属性不能这样处理 #输出结果 [<div data-foo="value">foo!</div>]
3)text参数
通过text参数可以搜索文档中的字符串内容。与name参数的可选值一样,text参数接受字符、正则表达式、列表、True
print soup.find_all(text=["Tillie", "Elsie", "Lacie"])
print soup.find_all(text=re.compile("Dormouse"))输出结果
[u'Elsie', u'Lacie', u'Tillie']
[u"The Dormouse's story", u"The Dormouse's story"]
4)limit参数
find_all()方法返回全部的搜索结构,如果文档树很大那么搜索会很慢2.如果我们不需要全部结果,可以使用limit参数限制返回结果的数量
soup.find_all('a',limit=2)值返回两条结果
5)recursive参数
调用tag的find_all()方法是,Beautiful Soup会检索当前tag的所有子孙节点,如果只想检索tag的直接子节点,可以使用参数
recusive=False
print(soup.find_all('mytitle')) print(soup.find_all('mytitle', recursive=False)) #输出结果 [<mytitle>The Dormouse's story</mytitle>] []
转载于:https://www.cnblogs.com/mnzht/p/9009753.html
Python中xPath技术和BeautifulSoup的使用相关推荐
- Python 中 xpath 语法 与 lxml 库解析 HTML/XML 和 CSS Selector
The lxml.etree Tutorial :https://lxml.de/tutorial.html python3 解析 xml:https://www.cnblogs.com/deadwo ...
- python中xpath定位_xpath最新:关于python中的xpath解析定位_爱安网 LoveAn.com
关于"xpath"的最新内容 聚合阅读 这篇文章主要介绍了关于python中的xpath解析定位,具有很好的参考价值,希望对大家有所帮助.一起跟随小编过来看看吧... 这篇文章主要 ...
- python中xpath语法怎么用_Python Xpath语法
一.python数据提取xpath 1.beautifulsoup xpath 正则表达式 2.xpath是一种在XML和HTML文档中查找信息的语言,可用来在XML和HTML中对元素进行遍历 Ch ...
- python中bs4.element.tag_python – BeautifulSoup标签是类型bs4.element.NavigableString和bs4.element.Tag...
我正在尝试在维基百科文章中搜索一个表,并且每个表元素的类型似乎都是< class'bs4.element.Tag'>和< class'bs4.element.NavigableStr ...
- python中xpath使用案例_python爬虫学习笔记:XPath语法和使用示例
python爬虫:XPath语法和使用示例 XPath(XML Path Language)是一门在XML文档中查找信息的语言,可以用来在XML文档中对元素和属性进行遍历. 选取节点 XPath使用路 ...
- python中xpath用法_Python中的xpath基础使用
前言: XPath 是一门在 XML 文档中查找信息的语言.XPath 用于在 XML 文档中通过元素和属性进行导航. XPath 含有超过 100 个内建的函数.这些函数用于字符串值.数值.日期和时 ...
- python中xpath如何获取内容_python requests + xpath 获取分页详情页数据存入到txt文件中...
直接代码,如有不懂请加群讨论 # *-* coding:utf-8 *-* # import json import requests import pytesseract import time i ...
- python中xpath用法_python xpath 基本用法
发布时间: pythonercn 8 months, 3 weeks ago 在进行网页抓取的时候,分析定位html节点是获取抓取信息的关键,目前我用的是lxml模块(用来分析XML文档结构的,当然也 ...
- python中xpath定位下拉菜单_Selenium2+Python3.6实战(八):定位下拉菜单出错,如何解决?用select或xpath定位。...
在登录界面,有时候会有几种不同的角色,针对不同角色定位到的信息是不一样的.查询资料知道定位下拉框的元素有两种方式:Xpath和select. 但是使用xpath定位时,user定位到了,登录的时候却是 ...
最新文章
- 青岛程序员加班看不上球赛崩溃,外卖小哥伸出援手:我帮你改代码
- boost::callable_traits的return_type_t的测试程序
- 定义坐标系-尚未成功
- java lambda表达式详解_Lambda表达式详解
- matlab from有什么用,Matlab函数使用'fromworkspace'将向量传递给simulink
- IBM “第8格(Debug)”开发者技术沙龙首站招募中,有胆你就来!
- 唏嘘!又一家手机工厂关闭,一代机皇彻底退出中国制造
- bzoj 3190 赛车 半平面交
- Twemproxy安装问题与不支持的操作明细
- 2021年游戏开发中的10大编程语言:C++、Java、C#......
- 如何下载贵州省卫星地图高清版大图
- wps表格宏被禁用如何解禁_wps excel宏被禁用如何启用 - 卡饭网
- dht11温湿度传感器工作原理引脚功能电路接线图
- 记录打包GoogleChrome浏览器插件
- 微信跳一跳小游戏源码
- 一个好用的windows文件搜索工具
- Bootstrap3 网页模板
- EventBus原理源码分析和使用
- 无线蓝牙手表FCC ID认证测试项目有哪些?
- 解决“windows已经阻止此软件因为无法验证发行者”方法
热门文章
- usd php 换算,货币在PHP中从INR转换为USD
- android 百度map 一个layout加载多个mapview,android 百度地图API 使用Marker和InfoWindow
- c和java内存泄漏区别_内存溢出和内存泄漏的区别(转)
- react 怎么获取表格_react学习之js-xlsx导入和导出excel表格
- linux进程创建时间,linux进程创建时间计算
- Navicat 连接Mysql 报错1251
- 从RedisTemplate中获得Jedis实例
- MySQL 数据库恢复
- 内蒙古工业大学计算机科学与技术,计算机科学与技术的应用领域简述论文内蒙古工业大学.doc...
- laravel 任务队列_laravel队列-让守护进程处理耗时任务