正则表达式(RegularExpression,re)
- 是一个计算机科学的概念
- 用于使用单个字符串来描述,匹配符合某个规则的字符串
- 常常用来检索,替换某些模式的文本
正则的写法
- .(点号):表示任意一个字符,除了\n,比如查找所有的一个字符.
- []:匹配中括号中列举的任意字符,比如[L,Y,0],LLY,Y0,LIU
- \d:任意一个数字
- \D:除了数字都可以
- \s:表示空格,tab键
- \S:除了空白符号
- \w:单词字符,就是a-z,A-Z,0-9
- \W:除了上面的这些
- :表示前面内容重复零次或者多次,\w
- +:表示前面内容至少出现一次
- ?:前面才出现的内容零次或一次
- {m,n}:允许前面内容至少出现m次,最多n次
- ^:匹配字符串的开始
- $:匹配字符串的结尾
- \b:匹配单词的边界
- ():对正则表达式内容进行分组,从第一个括号开始,编号逐渐增大
验证一个数字:^\d$
必须有一个数字,最少一位:^\d+$
只能出现数字,且位数为5-10位:^\d{5,10}$
注册者输入年龄,要求16岁以上,99岁以下:1$
只能输入英文字符和数字: 2$
验证qq号码: [0-9]{5,12} - \A: 只能匹配字符串开头, \Aabcd,则abcd
- \Z: 仅匹配字符串末尾, abcd\Z,abcd
- |:左右任意一个
-(?P…):分组,除了原来的编号再指定一个别名
-(?P=name):引用分组
RE使用大致步骤
- 使用compile将表示正则的字符串编译为一个pattern对象
- 通过pattern对象提供一系列方法对文本进行查找匹配,获得匹配结果,一个Match对象
- 使用Match对象提供的属性和方法获得信息,根据需要进行操作
Re常用函数
- group():获得一个或者多个分组匹配的字符串,当要获得整个匹配的子串时,直接使用group或者grope(0)
- start:获取分组匹配的子串在整个字符串中的起始位置,默认为0
- end: 获取分组匹配的子串在整个字符串的结束位置,默认为0
- span: 返回的结构技术(start(group),end(group))
import re
p = re.compile(r'\d+')
m = p.match("dafewr23rwefwf3rwfdw",6,16)
print(m)
<re.Match object; span=(6, 8), match=‘23’>
print(m[0])
print(m.start(0))
print(m.end(0))
23
6
8
import re
p = re.compile(r'([a-z]+) ([a-z]+)',re.I)#I表示忽略掉大写小写
m = p.match("I am really love chenxianrong")
print(m)
<re.Match object; span=(0, 4), match=‘I am’>
print(m.group(0))
print(m.start(0))
print(m.end(0))
I am
0
4
print(m.group(1))
print(m.start(1))
print(m.end(1))
I
0
1
print(m.groups())
(‘I’, ‘am’)
查找
- search(str,[,pos[,endpos]]):在字符串中查找匹配,pos和endpos表示起始位置
- findall:查找所有
- finditer:查找,返回一个iter结果
import re
p = re.compile(r'\d+')
m = p.search("dscfwerq323r34t3gt3432")
print(m.group())
323
rst = p.findall("wdwr23rwfr34r23wd")
print(type(rst))
print(rst)
<class ‘list’>
[‘23’, ‘34’, ‘23’]
sub替换
- sub(rep1,str[,count])
import re
p = re.compile(r'(\w+) (\w+)')
s = "hello 123 xiao 334534 rog,wwo 33 77"
rst = p.sub(r'Hello World',s)
print(rst)
Hello World Hello World rog,Hello World 77
匹配中文
- 大部分中文内容表示范围是(u4e00-u9fa5),不包括全角标点
import re
title = u'世界 你好啊,hello world'
p = re.compile(r'[\u4e00-\u9fa5]+')
rst = p.findall(title)
print(rst)
[‘世界’, ‘你好啊’]
贪婪和非贪婪
- 贪婪:尽可能多的匹配,(*)表示贪婪匹配
- 非贪婪:找到符合条件的最小内容即可,(*?)表示非贪婪
- 正则默认使用贪婪匹配
import re
title = u"<div>name</div><div>age</div>"
p1 = re.compile(r"<div>.*</div>")
p2 = re.compile(r"<div>.*?</div>")
m1 = p1.search(title)
print(m1.group())
m2 = p2.search(title)
print(m2.group())
<div>name</div><div>age</div>
<div>name</div>
爬取猫眼电影
from urllib import request
url = "http://maoyan.com/board"
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11"
}
req = request.Request(url,headers=headers)
rsp = request.urlopen(req)
html = rsp.read().decode()
import re
#缩小处理范围
s = r'<dd>(.*?)</dd>'
pattern = re.compile(s,re.S)
films = pattern.findall(html)
print(len(films))
# 从每一个dd中单独提取出需要的信息
for film in films:
s = r'<a.*?title="(.*)">'
pattern = re.compile(s)
title = pattern.findall(film)[0]
print(title)
10
我和我的祖国" class=“image-link” data-act=“boarditem-click” data-val="{movieId:1277939}
叶问4:完结篇" class=“image-link” data-act=“boarditem-click” data-val="{movieId:1190122}
速度与激情8" class=“image-link” data-act=“boarditem-click” data-val="{movieId:248700}
盗梦空间" class=“image-link” data-act=“boarditem-click” data-val="{movieId:416}
捉妖记" class=“image-link” data-act=“boarditem-click” data-val="{movieId:246083}
音乐家" class=“image-link” data-act=“boarditem-click” data-val="{movieId:1206829}
为国而歌" class=“image-link” data-act=“boarditem-click” data-val="{movieId:1256872}
狼图腾" class=“image-link” data-act=“boarditem-click” data-val="{movieId:78403}
天·火" class=“image-link” data-act=“boarditem-click” data-val="{movieId:1238837}
一出好戏" class=“image-link” data-act=“boarditem-click” data-val="{movieId:1203084}
Xpath
- 在XML文件中查找信息的一套规则/语言,根据XML的元素或者属性进行遍历
Xpath 开发工具
- 开源的Xpath表达式编辑工具:XMLQuire
- Chrome插件: Xpath Helper
- Firefox插件:Xpath Checker
选取节点
-
nodename: 选取此节点的所有子节点
-
/:从根节点开始选取
- /School:选取School节点
-
//:选取节点,不考虑位置
- //age:选取出三个节点,一般组成列表返回
-
.:选取当前节点
-
…:选取当前节点的父亲节点
-
@:选取属性
-
Xpath中查找一般按照路径方法查找
- School/Teacher:返回Teacher节点
- School/Student:返回两个Student节点
- //Student:选取所有Student的节点,不考虑位置
- School//Age:选取School后代中所有Age节点
- //@Other:选取Other属性
- //Age[@Detail]:选取带有属性的Age元素
-
谓语-Predicates
- /School/Student[1]:选取School下面的第一个Student节点
- /Schol/Student[last()]:选取School下面的最后一个Student节点
- /School/Student[last(-1)]:选取School下面的倒数第二个Student节点
- /Shool/Student[position()❤️]:选取School下面的前两个Student节点
- //Student[@score]:选取带有属性score的Student节点
- //Student[@score=“99”]:选取带有属性score并且属性值是99的Student节点
- //Student[@score]/Age:选取带有属性score的Student节点的子节点Age节点
-
Xpath的一些操作
- |:或者
- School/Teacher|School/Student:选取School节点下面的子节点Teacher和Student.
- +、-其他
- |:或者
# 案例
<?xml version="1.0" ending="utf-8" ?>
<School>
<Teacher desc="PythonTeacher" score="good">
<Name>LiuDana</Name>
<Age Detail="Age for year 2010">18</Age>
<Mobile>13260446055</Mobile>
</Teacher>
<Student>
<Name Other="班长">ZhangSan</Name>
<Age Detail="The yongest boy in class">14</Age>
</Student>
<Student>
<Name>LiSi</Name>
<Age>19</Age>
<Mobile>15578875040</Mobile>
</Student>
</School>
百度网站练习
#1、网站源代码获取及转换
import requests
from lxml import etree
r=requests.get("http://www.baidu.com")
# print ("状态码:",r.status_code)
# print ("网站源代码",r.text)
# print ("头部请求",r.headers)
html = etree.HTML(r.text) # 调用etree对象的属性HTML类进行初始化
etreeResult = etree.tostring(html) # 将其转化为字符串类型,etree类型
strResult=etreeResult.decode('utf-8') #转化为utf-8编码格式
print(strResult)
#2、节点、属性值、内容的获取
import requests
from lxml import etree
r=requests.get("http://www.baidu.com")
html = etree.HTML(r.text) # 调用HTML类进行初始化
resultAll = html.xpath('//*') #选取所有节点
#print("获取所有节点:",resultAll)
resultDivAll = html.xpath('//div') #选取div子孙节点
#print("获取div所有节点:",resultDivAll)
resultDiv_img = html.xpath('//div/img') #选取div下img节点
#print("获取div节点下img节点:",resultDiv_img)
resultDiv_imgSrc = html.xpath('//div/img/@src') #获取div_img的src属性值
print("获取div节点下img的src值:",resultDiv_imgSrc)
修饰符 描述
re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。