首页 > 其他分享 >正则表达式和XPath

正则表达式和XPath

时间:2023-04-22 15:24:16浏览次数:29  
标签:XPath 匹配 item 正则表达式 re html result etree

正则表达式

常用匹配规则

模式 描述
\w 匹配字母、数字以及下划线
\W 匹配不是字母、数字及下划线的字符
\s 匹配任意空白字符串,等价于[\t\n\r\f]
\S 匹配任意非空字符串
\d 匹配任意数字,等价与[0-9]
\D 匹配任意非数字的字符
\A 匹配字符串的开头
\Z 匹配字符串结尾。如果存在换行,只匹配到换行前的结束字符串
\z 匹配字符串结尾。如果存在换行,同时还会匹配换行符
\G 匹配最后匹配完成的位置
\n 匹配一个换行符
\t 匹配一个制表符
^ 匹配一行字符串的开头
$ 匹配一行字符串的结尾
. 匹配任意字符,除了换行符
[...] 用来表示一组字符,单独列出,例如[amk]用来匹配a、m或k
[^...] 匹配不在[]中的字符,例如匹配除a、b、c之外的字符
* 匹配0个或多个表达式
+ 匹配1个或多个表达式
? 匹配0个或1个前面的正则表达式片段,非贪婪模式
精确匹配n个前面的表达式
匹配n到m次由前面正则表达式定义的片段,贪婪模式
a|b 匹配a或b
() 匹配括号内的表达式,也表示一个组

match

向match传入匹配的字符串以及正则表达式,就可以检测正则表达式是否和字符串相匹配。

match方法会从字符串的起始位置开始匹配正则表达式,如果匹配返回匹配成功结果;不匹配返回None。

import re

content='Hello 123 4567 World_This is a Regex Demo'
print(len(content))   # 41
result=re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}',content)

print(result) # <_sre.SRE_Match object; span=(0,25),match='Hello 123 4567 World_This'
print(result.group()) # Hello 123 4567 World_This
print(resutl.span()) # (0,25)

^代表开头用Hello匹配;\s匹配空白符,用来匹配字符串中Hello后的空格;\d表示匹配数字,3个\d用来匹配123;\s匹配后面的空格;\d{4}代表匹配4次数字;空格;\w{10}表示匹配10个字母、数字及下划线

group输出匹配到的内容;span方法输出匹配的范围,结果字符串在原字符串的位置范围

匹配目标

将()把想提取的字字符串括起来,就可以提取字符串中的一部分内容。()实际标记一个子表达式的开始和结束位置,被标记的每个子表达式依次对应分组。

import re

content='Hello 1234567 World_This is a Regex Demo'
result=re.match('^Hello\s(\d+)\sWorld',content)
print(result)    # <_sre.SRE_Match object; span=(0,19),match='Hello 1234567 World'
print(result.group())  # Hello 1234567 World
print(result.group(1)) # 1234567
print(result.span())	 # (0,19)

通用匹配

.可以万能匹配,.可以匹配任意字符(除换行符*),*代表前面字符的无限次,

import re

content='Hello 123 4567 World_This is a Regex Demo'
result=re.match('^Hello.*Demo$',content)
print(result)    # <_sre.SRE_Match object; span=(0,41),match='Hello 123 4567 World_This is a Regex Demo'>
print(result.group())  # Hello 123 4567 World_This is a Regex Demo
print(result.span())	 # (0,41)

贪婪与非贪欲

import re

content='Hello 1234567 World_This is a Regex Demo'
result=re.match('^He.*(\d+).*Demo&',content)
print(result)   # <_sre.SRE_Match object; span=(0,40),match='Hello 1234567 World_This is a Regex Demo'>
print(result.group(1))  # 7

在贪欲模式下,.会匹配尽可能多的字符。正则表达式中,.后面是\d+,也就是至少一个数字,而且没有指定具体几个数字,因此,.***会匹配尽可能多的字符,所以就把123456全匹配了,只留下了一个可满足条件的数字了

当在^He.*?(\d+).*Demo$加上一个?号就会变为非贪婪模式。当.*?匹配到Hello后面的空白字符时,再往后就是数字了,而\d+恰好可以匹配,与.就不在匹配,而是交给.*?*去匹配。

如果.*?在字符串结尾,就可能匹配不到任何内容了,因为他会匹配尽可能少的字符

import re

content='http://weibo.com/comment/kEraCN'
result1=re.match('http.*?comment/(.*?)',content)
result2=re.match('http.*?comment/(.*)',content)
print('result1',result1.group(1))					# result1
print('result2',result2.group(1))					# result2 kEraCN

修饰符

# 在正则表达式中可以用一些可选标志修饰符来控制匹配模式。
import re

content="""Hello 1234567 World_This
is a Regex Demo
"""
result=re.match=('^He.*?(\d+).*?Demo$',content)
print(result.group(1))  # 运行报错

因为匹配的内容是除换行符以外的任意字符,当遇到.*?就不能匹配了,只需加上修饰符re.S既可修正错误

修饰符 描述
re.I 使匹配对大小写不敏感
re.L 实现本地化识别(locale-aware)匹配
re.M 多行匹配,影响(^和$)
re.S 是匹配内容包括换行符在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志会影响\w、\W、\b、\B
re.X 该标志能够给予更灵活的格式
import re

content='Extra stings Hello 1234567 World_This is a Regex Demo Extra    stings'
result=re.match('Hello.*?(\d+).*>?Demo',content)
print(result)  # None

因为match方法会从字符串头开始匹配,因此在使用时需要考虑目标字符串的开头内容。

search会扫描整个字符串,然后返回第一个匹配成功的结果。

findall

如果需要获取与正则表达式相匹配的所有字符串,则可以使用findall方法。

sub

使用正则表达式除了可以提取信息,还可以用来修改信息。

import re

content='3453hdfjgl3453jjk'
content=re.sub('\d+','',content)
print(content) # hdfjgjjk

compile

可以将字符串编译成正则表达式对象,重复使用

import re

content1='2019-12-15 12:00'
content2='2019-12-17 12:55'
content3='2019-12-22 13:21'
patten=re.compile('\d{2}:\d{2}')
result1=re.sub(patten,'',content1)
result2=re.sub(patten,'',content2)
result3=re.sub(patten,'',content3)
print(result1,result2,result3) # 12:00 12:55 13:21
# 使用compile方法将正则表达式编译成一个正则表达式对象,完成复用,在借助sub方法去掉日期

XPath

当使用正则表达式在网页比较复杂,内容较多时不方便调试。所以可以先获取标签的节点然后获取标签下相应的值

常用表达式

表达式 描述
nodename 选取此节点的所有子节点
/ 从当前节点选取直接子节点
// 从当前节点选取子孙节点
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性

基本使用

渲染所有

from lxml import etree

text = '''
<div> 
<ul>
<li class="item-0"><a href="link.1html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</ul>
</div>
'''

def default():
    html = etree.HTML(text)
    result = etree.tostring(html)
    print(result.decode('utf-8'))
# 即使最后的li标签没有闭合,使用tostring方法即可修正html代码,但是结果是bytes类型,使用decode进行转换    

获取节点

获取所有节点
from lxml import etree

html = etree.parse('test.html', etree.HTMLParser())
# 以//开头的Xpath规则匹配,//*代表匹配所有的节点
html.xpath('//*')

# 匹配节点下所有的li节点,用索引获取具体
result=html.xpath('//li')
result[index]
子节点
from lxml import etree

html = etree.parse('test.html', etree.HTMLParser())

# 获取li节点下的所有子节点a
html.xpath('//li/a')

# 获取ul节点下所有的子孙节点a
html.xpath('//ul//a')
父节点
from lxml import etree

html = etree.parse('test.html', etree.HTMLParser())
# 获取link4的父节点的class属性
result=html.xpath('//a[@href="link4.html"]/../@class')  # ['item-1']
# 也可以使用parent::获取父节点
html.xpath('//a[@href="link4.html"]/parent::*/@class')
属性匹配
from lxml import etree

html = etree.parse('test.html', etree.HTMLParser())
# 根据符号@进行属性过滤
html.xpath('//li[@class="item-0"]')
文本获取
from lxml import etree

html = etree.parse('test.html', etree.HTMLParser())
# 获取li下面的文本内容
rest=html.xpath('//li[@class="item-0"]/text()')
print(rest)  #['\n  ']
# 因为li下还有一个a标签所以还需加上一个a标签  //li[@class="item-0"]/a/text()   ['first item','first item']

#直接使用子孙获取
rest=html.xpath('//li[@class="item-0"]//text()')
print(rest)
# ['first item','first item','\n     ']
属性获取
from lxml import etree

html = etree.parse('test.html', etree.HTMLParser())
# 获取属性的值,而非属性的类型进行匹配
rest=html.xpath('//li/a/@href')
print(rest)
#['link1.html','link2.html','link3.html','link4.html','link5.html']
属性多值匹配
from lxml import etree

text='''
<li class="li li-first"><a href="link.html"></a>first html</li>
'''

html = etree.HTML(text)

# 当遇到class为多属性时使用[@class="li"]将不起作用,需要使用contains
rest=html.xpath('//li[contains(@class,"li")]/a/text()')
print(rest)
# ['first item']
多属性匹配

Xpath运算符

运算符 描述
or
and
mod 计算除法的余数
| 计算两个节点集
+ 加法
- 减法
* 乘法
div 除法
= 等于
!= 不等于
< 小于
<= 小于或等于
> 大于
>= 大于或等于
from lxml import etree

text='''
<li class="li li-first" name="item"><a href="link.html"></a>first html</li>
'''

html = etree.HTML(text)

# 使用运算法进行连接
html.xpath('//li[contains(@class,"li") and @name="item"]/a/text()')
按序选择
from lxml import etree

text="""
<div>
<ul>
<li class='item-0'><a herf="link1.html">first item</a></li>
<li class='item-1'><a herf="link2.html">second item</a></li>
<li class='item-inactive'><a herf="link3.html">third item</a></li>
<li class='item-0'><a herf="link4.html">fourth item</a></li>
<li class='item-1'><a herf="link5.html">fifth item</a></li>
</ul>
</div>
"""

html=etree.HTML(text)
# 下标为1的li的a标签文本内容
result=html.xpath('//li[1]/a/text()')
print(result)		#'[first item]'

# 下标为最后一个li的a标签文本内容
result=html.xpath('//li[last()]/a/text()')
print(result) 	# ['fifth item']

# 下标为li位置小于3的a标签文本内容
result=html.xpath('//li[position()<3]/a/text()')
print(result)		# ['first item','second item']

# 下标为最后li减去2个位置的a标签文本内容
result=html.xpath('//li[last()-2]/a/text()')
print(result)		# ['third item']

标签:XPath,匹配,item,正则表达式,re,html,result,etree
From: https://www.cnblogs.com/kangkin/p/17343136.html

相关文章

  • jmeter正则表达式
     正则表达式关联:下一次请求会用到上一次请求的返回参数    验证cookie提取成功 提取出参的msg 接口测试的流程 ......
  • 正则表达式
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=d......
  • 正则表达式获取字符串中电话号码的方式
    我一开始是想找数字1然后切出11位数字这样但是newbing给了一个简单了当的方法正则表达式直接切11位数字分享出来以供参考/***@Description:正则表达式寻找字符串中的电话号码*@paramstring有11位电话存在的字段*@author:@NewBing**/......
  • iOS:常用的正则表达式
    转载自Swift正则表达式-简书(jianshu.com)数字:^[0-9]*$n位的数字:^\d{n}$至少n位的数字:^\d{n,}$m-n位的数字:^\d{m,n}$零和非零开头的数字:^(0|[1-9][0-9]*)$非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?......
  • 在Scrapy中如何利用Xpath选择器从HTML中提取目标信息(两种方式)
    今日鸡汤坚定,严谨,勤奋,开拓今天我们将介绍在Scrapy中如何利用Xpath选择器从HTML中提取目标信息。在Scrapy中,其提供了两种数据提取的方式,一种是Xpath选择器,一种是CSS选择器,这一讲我们先聚焦Xpath选择器,仍然是以伯乐在线网为示例网站。1、 打开网站,然后随机选择任意一篇文章进行查看......
  • 正则表达式
    正则表达式正则表达式是一组由字母和符号组成的特殊文本,它可以用来从文本中找出满足你想要的格式的句子。一个正则表达式是一种从左到右匹配主体字符串的模式。“Regularexpression”这个词比较拗口,我们常使用缩写的术语“regex”或“regexp”。正则表达式可以从一个基础字符串......
  • 常用正则表达式
    1、日期格式yyyy-MM-dd包括正确性验证^[0-9]{4}-(((0[13578]|(10|12))-(0[1-9]|[1-2][0-9]|3[0-1]))|(02-(0[1-9]|[1-2][0-9]))|((0[469]|11)-(0[1-9]|[1-2][0-9]|30)))$2、日期格式yyyy-MM包括正确性验证^[0-9]{4}-(((0[13578]|(10|12)))|(02-(0[1-9]|[1-2][0-9]))|((0......
  • JS正则表达式大全
    评:原文很多没有全部黏贴过来字符含意\做为转意,即通常在"\"后面的字符不按原来意义解释,如/b/匹配字符"b",当b前面加了反斜杆后/\b/,转意为匹配一个单词的边界。-或-对正则表达式功能字符的还原,如"*"匹配它前面元字符0次或多次,/a*/将匹配a,aa,aaa,加了"\"后,/a\*/将只匹配"a*"。^匹配一......
  • 正则表达式
    正则表达式的基本知识正则表达式是一种描述字符串结果的语法规则,是一个特定的格式化模式,可以匹配、替换、截取匹配的字符串。常用的语言基本上都有正则表达式,如JavaScript、java等。其实,只有了解一种语言的正则使用,其他语言的正则使用起来,就相对简单些。行定位符(^与$)行定位符是......
  • 正则表达式--正负整数
    BOOLCheckNumValid(CStringstrIn){ wstringszName=strIn.GetBuffer(); strIn.ReleaseBuffer(); std::wregexreg(L"^(([1-9]+\d*)|(0{1}))(.\d{1,2})?"); std::wsmatchresult; BOOLbIsValid=regex_match(szName,result,reg); if(!bIsValid) {......