Python的正则表达式
- 非结构化数据 现有数据,再有介机构 如: HTML
- 结构化输数据 现有结构,再有数据 如: JSON
正则表达式
贪婪模式:
在匹配成功的情况下,才有贪婪与非贪婪
尽可能多的匹配
如:
preg = 'abbbb';
re.finall('ab*', preg)
结果:
['abbbb']
非贪婪模式:
在匹配成功的情况下,才有贪婪与非贪婪
尽可能少的匹配
preg = 'abbbb';
# *标识前面这个可以,匹配0次或多次, 可以有也可以没有.
# 前面的* 匹配成功了之后, ?前面这个启动非贪婪模式, 尽可能少的匹配(即为不匹配)
re.finall('ab*?', preg)
结果:
['a']
# 如果不明白*?的话可以对比一下+,匹配一次或多次
# 而一旦+匹配成功, ?设置前面为,尽可能少的匹配
re.finall('ab+?', preg)
记过:
['ab']
先决条件
# _*_ encoding:utf-8 _*_
# 引入正则表达式Module
import re
# re.compile() 可以不用这个方法, 但是compile是起到了编译作用, 使正则的匹配速度更快一点
# re.compile() 把正则表达式的字符串编译成一个 pattern 对象
# r关键字对特殊字符需要转义
preg = re.compile(r'\d+')
- match(string, pos, endpos)
match从字符串的开头(或指定位置)进行匹配,如果在开头没找到就返回None,
只匹配一次,匹配到结果就不在匹配了
# 匹配条件
result = preg.march('one123two456')
print(result)
# 结果
None
# 修正,从第3个开始匹配,匹配到第10个
result = preg.march('one123two456', 3, 10)
print(result)
结果
返回正则对象: <_sre.SRE_Match object; span=(3, 6), match='123'>
使用: result.group()获取结果为: 123
- sarch(string, pos, endpos)
search 匹配整个字符串,也可以指定匹配的位置
只匹配一次,匹配到结果就不在匹配了
# 匹配条件
result = pattern.search('one123two456')
# 结果
返回正则对象: <_sre.SRE_Match object; span=(3, 6), match='123'>
使用: result.group()获取结果为: 123
- finall(string, pos, endpos)
获取所有的匹配结果
# 匹配条件
result = pattern.findall('one123two456')
print(result)
# 结果
失败: 返回一个空list. 如: []
成功: 返回一个包含所有的list
['123', '456']
- sub(pattern, repl, string, count=0, flags=0)
替换匹配到的字符串
# 将以下几个HTML标签替换为空,同时将结果赋值到iterm中
re.sub(r'&\w+;|<p>|</p>|<br />', '', iterm)
二.常用的re函数:
方法/属性 作用
re.match(pattern, string, flags=0) 从字符串的起始位置匹配,如果起始位置匹配不成功的话,match()就返回none
re.search(pattern, string, flags=0) 扫描整个字符串并返回第一个成功的匹配
re.findall(pattern, string, flags=0) 找到RE匹配的所有字符串,并把他们作为一个列表返回
re.finditer(pattern, string, flags=0) 找到RE匹配的所有字符串,并把他们作为一个迭代器返回
re.sub(pattern, repl, string, count=0, flags=0) 替换匹配到的字符串
函数参数说明:
pattern:匹配的正则表达式
string:要匹配的字符串
flags:标记为,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
repl:替换的字符串,也可作为一个函数
count:模式匹配后替换的最大次数,默认0表示替换所有匹配
xpath
URL:http://blog.jobbole.com/110287/ 获取文章标题
Chrome复制的xpath
//*[@id="post-110287"]/div[1]/h1
Firefox复制的xapth
/html/body/div[3]/div[3]/div[1]/div[1]/h1
理论上来讲,两个都没问题, 通过F12控制台查看也都没有问题,
虽然写法不同,但是看起来没有问题.
但是在实际使用中发现Firefox提供的并不能用
经过分析发现:
Firefox提供的是绝对路径, 即从根开始,而且提供的是和控制台一样的代码顺序.
而且在body/div并不是第三个,应该是第一个,前面两个是JS生成的.
实际上是应该按照源码,查看,即在页面点击查看源码,这里的代码才是对的.
chrome提供的是从ID开始,ID和我们想要的元素比较近,所以没有出问题.
平时使用当中,应该注意这一点.
结论:
我们在平时使用当中, 需要提取xpath时,通过控制台看代码得时候,要注意HTML的颜色提示.
js生成的代码不能算在内, 必要的时候可以通过查看页面源码来对比浏览器给得xpath对不对.
一般情况下, 我们也不要从根开始拼节点.
article 选取所有article元素的子节点
/article 选取根元素article
article/a 选取所有属于article的子元素的a元素
//div 选取所有div子元素(不论出现在文档何种位置)
article//div 选取所有属于article元素的后代的div元素
//@class 选取所有名为class的属性
/article/div[1] 选取属于article子元素的第一个元素
/article/div[last()] 选取属于article子元素的最后一个元素
/article/div[last()-1] 选取属于article子元素的倒数第二个元素
//div[@lang] 选取所有拥有lang属性的div元素
//div[@lang='eng'] 选取所有lang属性为eng的div元素
/div/* 选取属于div元素的所有子元素
//* 选取所有元素
//div[@*] 选取所有带有属性的title元素
/div/a|//div/p 选取所有div元素的a和p元素
//span|//ul 选取文档中的span和ul元素
article/div/p|//span 选取所有属于article元素的div元素的p元素以及文档中的所有的span元素
text() 获取文字内容
contains() 获取匹配到的元素
如:
//span[contains(@class, 'vote-post-up')]
获取class中含有vote-post-up名的class, 当一个class有多个名字的时候用这个特别好
/从根节点选取
//从匹配选择当前节点匹配所有
.选择当前节点
@选取HTML的属性 class id src href
xpath 是可以运算的
| 并集 + -
//book # 选取所有的book元素, 不考虑位置
//@ddd # 选取所有名为ddd的属性
# 匹配该含有该class属性的所有div下的所有a节点的href属性
//div[@class="threadlist_title pull_left j_th_tit "]//a/@href
# 匹配所有div下的img含有BED_Image属性的src属性
//div/img[@class="BDE_Image"]//@src
CSS选择器
* 选择所有节点
#container 选择ID为containerd的节点
.container 选取所有class为container的节点
.containser.next 选取同时含有.containser.next 的class
li a 选取所有li下的a节点
ul + p 选择ul后面的第一个p元素
div#container > ul 选取id为container的div的第一个ul子元素
ul ~ p 选取与ul相邻的所有p元素
a[title] 选取所有title属性的a元素
a[href="http://jobole.com"] 选取所有href属性为jobbole.com值的a元素
a[href*="jobbole"] 选取所有href属性包含jobbole的a元素
a[href^="http"] 选取所有href属性值以http开头的a元素
a[href$=".jpg"] 选取所有href属性值以.jpg结尾的a元素
input[type=radio]:checked 选取选中的radio的元素
div:not(#container) 选取所有ID为非container的div元素
li:nth-child(3) 选取子类中的第三个li元素
tr:nth-child(2n) 选取子类中的第偶数个tr
::text 获取文字内容
::attr(属性) 获取指定属性的值