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的使用相关推荐

  1. Python 中 xpath 语法 与 lxml 库解析 HTML/XML 和 CSS Selector

    The lxml.etree Tutorial :https://lxml.de/tutorial.html python3 解析 xml:https://www.cnblogs.com/deadwo ...

  2. python中xpath定位_xpath最新:关于python中的xpath解析定位_爱安网 LoveAn.com

    关于"xpath"的最新内容 聚合阅读 这篇文章主要介绍了关于python中的xpath解析定位,具有很好的参考价值,希望对大家有所帮助.一起跟随小编过来看看吧... 这篇文章主要 ...

  3. python中xpath语法怎么用_Python Xpath语法

    一.python数据提取xpath 1.beautifulsoup xpath 正则表达式 2.xpath是一种在XML和HTML文档中查找信息的语言,可用来在XML和HTML中对元素进行遍历  Ch ...

  4. python中bs4.element.tag_python – BeautifulSoup标签是类型bs4.element.NavigableString和bs4.element.Tag...

    我正在尝试在维基百科文章中搜索一个表,并且每个表元素的类型似乎都是< class'bs4.element.Tag'>和< class'bs4.element.NavigableStr ...

  5. python中xpath使用案例_python爬虫学习笔记:XPath语法和使用示例

    python爬虫:XPath语法和使用示例 XPath(XML Path Language)是一门在XML文档中查找信息的语言,可以用来在XML文档中对元素和属性进行遍历. 选取节点 XPath使用路 ...

  6. python中xpath用法_Python中的xpath基础使用

    前言: XPath 是一门在 XML 文档中查找信息的语言.XPath 用于在 XML 文档中通过元素和属性进行导航. XPath 含有超过 100 个内建的函数.这些函数用于字符串值.数值.日期和时 ...

  7. python中xpath如何获取内容_python requests + xpath 获取分页详情页数据存入到txt文件中...

    直接代码,如有不懂请加群讨论 # *-* coding:utf-8 *-* # import json import requests import pytesseract import time i ...

  8. python中xpath用法_python xpath 基本用法

    发布时间: pythonercn 8 months, 3 weeks ago 在进行网页抓取的时候,分析定位html节点是获取抓取信息的关键,目前我用的是lxml模块(用来分析XML文档结构的,当然也 ...

  9. python中xpath定位下拉菜单_Selenium2+Python3.6实战(八):定位下拉菜单出错,如何解决?用select或xpath定位。...

    在登录界面,有时候会有几种不同的角色,针对不同角色定位到的信息是不一样的.查询资料知道定位下拉框的元素有两种方式:Xpath和select. 但是使用xpath定位时,user定位到了,登录的时候却是 ...

最新文章

  1. 青岛程序员加班看不上球赛崩溃,外卖小哥伸出援手:我帮你改代码
  2. boost::callable_traits的return_type_t的测试程序
  3. 定义坐标系-尚未成功
  4. java lambda表达式详解_Lambda表达式详解
  5. matlab from有什么用,Matlab函数使用'fromworkspace'将向量传递给simulink
  6. IBM “第8格(Debug)”开发者技术沙龙首站招募中,有胆你就来!
  7. 唏嘘!又一家手机工厂关闭,一代机皇彻底退出中国制造
  8. bzoj 3190 赛车 半平面交
  9. Twemproxy安装问题与不支持的操作明细
  10. 2021年游戏开发中的10大编程语言:C++、Java、C#......
  11. 如何下载贵州省卫星地图高清版大图
  12. wps表格宏被禁用如何解禁_wps excel宏被禁用如何启用 - 卡饭网
  13. dht11温湿度传感器工作原理引脚功能电路接线图
  14. 记录打包GoogleChrome浏览器插件
  15. 微信跳一跳小游戏源码
  16. 一个好用的windows文件搜索工具
  17. Bootstrap3 网页模板
  18. EventBus原理源码分析和使用
  19. 无线蓝牙手表FCC ID认证测试项目有哪些?
  20. 解决“windows已经阻止此软件因为无法验证发行者”方法

热门文章

  1. usd php 换算,货币在PHP中从INR转换为USD
  2. android 百度map 一个layout加载多个mapview,android 百度地图API 使用Marker和InfoWindow
  3. c和java内存泄漏区别_内存溢出和内存泄漏的区别(转)
  4. react 怎么获取表格_react学习之js-xlsx导入和导出excel表格
  5. linux进程创建时间,linux进程创建时间计算
  6. Navicat 连接Mysql 报错1251
  7. 从RedisTemplate中获得Jedis实例
  8. MySQL 数据库恢复
  9. 内蒙古工业大学计算机科学与技术,计算机科学与技术的应用领域简述论文内蒙古工业大学.doc...
  10. laravel 任务队列_laravel队列-让守护进程处理耗时任务