标签:print ret 表达式 挖掘 掌握 poc dea 单词 test
微信阅读:网罗天下之~正则表达
微在线预览:http://github.lesschina.com/python/spider/re/1.网罗天下之-正则表达.html
字符 | 含义 |
---|---|
. |
匹配任意1个字符(除了\n ) |
[] |
匹配[ ] 中列举的1个字符(^ 可以取反) |
\d |
匹配数字(0~9 ) |
\D |
匹配非数字(非数字 ) |
\s |
匹配空白(空格、Tab键、回车 ) |
\S |
匹配非空白 |
\w |
匹配单词字符,即a-z、A-Z、0-9、_ (包括单个中文字符) |
\W |
匹配非单词字符 |
注意:
\s
并不匹配""
<re.Match object; span=(0, 1), match=‘\t‘>
match=xxx
,就是我们ret.group()
的结果# 定义一个通用测试方法
import re
def my_match(re_str, input_str):
ret = re.match(re_str, input_str)
if ret:
print(f"[匹配结果:{ret.group()}]")
else:
print(f"[{input_str}不匹配]")
return ret
# Python中字符串前面加上 r 表示原生字符串(不转义)
# \s 验证
# 空格匹配验证
my_match("\s"," ")
# Tab键匹配验证
my_match("\s","\t")
# 回车匹配验证
my_match("\s","\n")
# 不匹配验证:(空字符串)
my_match("\s","")
# \d 验证
# 匹配单个数字
my_match("\d","1") # 一点要变成字符串
# 多个数字则只能匹配一个字符
my_match("\d","11") # 注意
# 解决:以^开头,以$结尾
my_match("^\d$","11")
# [] 验证
# 不是1、2、3则不匹配
my_match("[1-3]","4")
# 匹配1~3,6~9
my_match("[1-36-9]","7")
# 不匹配验证
my_match("[1-36-9]","5")
# 只匹配数字和字母(大小写)
my_match("[\da-zA-Z]","7")
my_match("[\da-zA-Z]","b")
my_match("[\da-zA-Z]","B")
# 不匹配验证
my_match("[\da-zA-Z]","_")
# [] 取反扩展
# \d ==> [0-9]
# \D ==> [^0-9]
# 非2、4、6
my_match("[^246]","3")
my_match("[^246]","@")
# 错误验证
my_match("[^246]","4")
# 非 1~6
my_match("[^1-6]","7")
my_match("[^1-6]","#")
# 错误验证
my_match("[^1-6]","5")
# \w在UTF8下会匹配中文的验证:
my_match("\w","滚")
# .匹配任意字符,不包括\n的验证:
my_match(".","\n")
# 除了\n,可以匹配任意一个字符
my_match(".","\t")
# 扩展
# 如果想让.支持\n,再多传个flag:re.S
re.match(".","\n",re.S)
字符 | 含义 |
---|---|
* |
1个字符出现次数:>=0 |
+ |
1个字符出现次数:>=1 |
? |
1个字符出现次数:1 or 0 |
{m} |
1个字符出现m 次 |
{m,n} |
1个字符出现从[m,n] 次 |
\ |
转义特殊字符 |
^ |
匹配字符串开头 |
$ |
匹配字符串结尾 |
多个字符,一般都是以^
开头,以$
结尾,不然容易出Bug(re.match
方法默认以^
开头)
PS:vi
命令模式下,输入^
和$
,光标会跳转到头和尾
Python中r""
代表不转义字符串:
# r"",如果包含转义字符\就容易出错了,这时候r""就上场了
re.match("\\mmd","\mmd")
# 原因分析
# \是有特殊含义的,想要没有特殊含义就再加个\,
# 那加上的这个\又有特殊含义,所以就蛋疼了,r""这时候就上场了
# 解决方法
re.match(r"\\mmd","\\mmd") # 下面有案例
# * 、 + 、?
# *:0个或者多个
my_match(r"\d*","")
my_match(r"\d*","11")
# +:1个或者多个
# 不匹配验证:
my_match(r"\d+","")
# 匹配验证:
my_match(r"\d+","1")
my_match(r"\d+","11")
# ?:0个或者1次
# 不匹配验证:
my_match(r"^\d?$","11")
# 匹配验证
my_match(r"^\d?$","")
my_match(r"^\d?$","1")
# 为什么用^和$包裹,看下面两个奇葩案例就知道了
my_match("\d","123333")
my_match("\d*","a") # ==> "a" ==> """a"
# {}指定位数验证
# ? ==> {0,1}
# 1位数字或者2位数字
my_match(r"^\d{1,2}$","7")
# 1位数字或者2位数字
my_match(r"^\d{1,2}$","17")
# 错误验证
my_match(r"^\d{1,2}$","777")
# 指定位数 eg:10位数字
my_match(r"^\d{10}$","1234567890")
# 错误验证 ~ 9位
my_match(r"^\d{10}$","123456789")
# 错误验证 ~ 非整数
my_match(r"^\d{10}$","A123456789")
# {} 扩展
# * ==> {0,}
# + ==> {1,}
# \d 至少3个
my_match(r"\d{3,}","123")
my_match(r"\d{3,}","1234")
# 错误验证
my_match(r"\d{3,}","12")
# ^ $ 案例
# 验证变量命名
my_match(r"^[a-zA-z_]\w*$","a_bbp")
my_match(r"^[a-zA-z_]\w*$","_")
# 测试一个就知道为什么用\w了
def test蛋():
print("mmd")
test蛋() # Python Code
# 如果没有加开头和结尾的Bug测试
# 没有判断结尾的Bug案例
my_match(r"[a-zA-z_]\w*","a_b#w")
# 测试Bug,这个也匹配了
my_match(r"[a-zA-z_]+@qq.com","mmd@qq.comcom")
# 改进 ~ 现在不匹配了
my_match(r"^[a-zA-z_]\w*$","a_b#w")
# 转义字符 \ 引入案例
# 测试Bug,这个也匹配了
my_match(r"[a-zA-z_]+@qq.com","mmd@qq#comcom")
# 改进 ~ 现在不匹配了 (开头结尾+\转义)
my_match(r"^[a-zA-z_]+@qq\.com$","mmd@qq#comcom")
# r"",如果包含转义字符\就容易出错了,这时候r""就上场了
try:
my_match("\\mmd","\mmd")
except Exception as ex:
print(ex)
# 原因分析
# \是有特殊含义的,想要没有特殊含义就再加个\,
# 那加上的这个\又有特殊含义,所以就蛋疼了,r""这时候就上场了
# 解决方法
my_match(r"\\mmd", "\\mmd")
字符 | 含义 | |
---|---|---|
\ | 匹配左右任意一个表达式 | |
\b |
匹配一个单词的边界(字母与空格间的位置) | |
\B |
匹配非单词的边界 | |
( ) |
将括号中字符作为一个分组 | |
\num |
引用分组num匹配到的字符串 | |
(?P<name>) |
分组起别名 | |
(?P=name) |
引用别名为name分组匹配到的字符串 |
# 匹配边界
# \b 匹配以net结尾的单词
my_match(r"\w+net\b","dotnet")
my_match(r"\w+net\b","dotnet crazy")
# 不匹配验证
my_match(r"\w+net\b","dotnetcrazy")
# 后面会讲
re.findall(r"\w+net\b","dotnet crazy aspnet")
# 不匹配验证:\b、\B、^、$只是代表边界,并不表示空格
my_match(r"\w+\bnet\b","dot net crazy")
# 正确修改
my_match(r"\w+\s\bnet\b","dot net crazy")
# 把上面换成\B,则代表单词间必须是 非空格的字符
my_match(r"\w+\Bnet\B","dotnetcrazy")
my_match(r"\w+\Bnet\B","dotnetAcrazy")
my_match(r"\w+\Bnet\B","dotnet1crazy")
# 不匹配验证
my_match(r"\w+\Bnet\B","dotnet#crazy")
# | 匹配左右任意一个表达式
# 匹配小明或者小张
my_match(r"^小明|小张$","小明")
my_match(r"^小明|小张$","小张")
# 不匹配验证
my_match(r"^小明|小张$","小潘")
# () 将括号中字符作为一个分组
# group(1) 返回第1个括号匹配内容
my_match(r"^[a-zA-Z0-9_]+@(qq|163)\.com$","mmd@163.com").group(1)
# HTML的标签匹配匹配检查
my_match(r"^<([a-zA-Z1-9]+)>.*</\1>$","<h1>萌萌哒</h1>").group(1)
# groups返回所有的匹配结果
my_match(r"^<([a-zA-Z1-9]+)><([a-zA-Z1-9]+)>(.*)</\2></\1>$","<p><font>我去</font></p>").groups()
# 匹配 qq.com 和 163.com (别忘记转义.)
ret = my_match(r"(^[a-zA-Z0-9_]+)@(qq|163)\.com$","mmd@qq.com")
print(ret.groups())
ret = my_match(r"(^[a-zA-Z0-9_]+)@(qq|163)\.com$","mmd@163.com")
print(ret.groups())
# 不匹配验证
my_match(r"^(^[a-zA-Z0-9_]+)@(qq|163)\.com$","@163.com")
my_match(r"^(^[a-zA-Z0-9_]+)@(qq|163)\.com$","mmd@123.com")
# 别名案例(不常用)
my_match(r"<(?P<mmd>\w*)><(?P<dnt>.*)>.*</(?P=dnt)></(?P=mmd)>","<html><h1>萌萌哒</h1></html>").group(2)
# 不匹配验证
my_match(r"<(?P<mmd>\w*)><(?P<dnt>.*)>.*</(?P=dnt)></(?P=mmd)>","<html><h1>萌萌哒</h2></html>")
# 练练手
# 1~100之间的数字:(1,100)
my_match(r"^[1-9]\d?$","0")
my_match(r"^[1-9]\d?$","7") # 十位只能是1~9
my_match(r"^[1-9]\d?$","77")
# 不匹配验证
my_match(r"^[1-9]\d?$","07")
my_match(r"^[1-9]\d?$","777")
# 0~100的数字:[0,100]
re_str=r"^([1-9]?\d?|100)$" # ^([1-9]\d?|100|0)$
my_match(re_str,"0")
my_match(re_str,"1")
my_match(re_str,"70")
my_match(re_str,"100")
# 不匹配验证
my_match(re_str,"07")
my_match(re_str,"170")
my_match(re_str,"700")
上面的都是通用系列,下面的才能体现为啥爬虫是Python的优势:
re.match
:和其他语言用法一致(默认从头开始匹配)re.search
:匹配第一个并返回(如果加了^
和$
就和match一样了)re.findall
:返回所有匹配的列表re.sub
:将匹配到的数据进行替换,再返回新的字符串
re.split
:正则切割函数(类似于字符串的split)re.compile
:正则字符串编译成正则表达式对象# 匹配第一个就结束了
ret = re.search(r"\d","我的名字叫小明,今年23,88")
print(ret.group())
# 如果加了开头结尾就和match一样了
print(re.search(r"^\d$","我的名字叫小明,今年23,88"))
# 返回所有匹配的列表
re.findall(r"\d","我的名字叫小明,今年23,88")
re.split(r",|。","我的名字叫小明,今年23。88")
# sub案例:批量替换1
re.sub(r"\d+","***","我上次买的时候98.5块,现在30就拿到了,差评!")
# sub案例:批量替换2 ~ 拿到分组内容并进行处理
re.sub(r"(\d+)",r"400\1","我是小明,客服电话是:6789688")
# sub案例:函数处理
def shit_test(result):
# 返回类型必须是str
return str(float(result.group())*2)
re.sub(r"\d+",shit_test,"我上次买的时候98.5块,现在30就拿到了,差评!")
# 扩展内容
pattern = re.compile(r"A.*Z",re.S) # 表达式复用
print(re.match(pattern,"ABZ").group())
print(re.match(pattern,"ACZ").group())
# 练手小案例
# 提取单词
input_str = "Python Golang NetCore JavaScript"
print(re.split(" ",input_str))
re.findall("[a-zA-Z]+",input_str)
# 提取文字 """ 保留字符串原始格式
html_str = """
<div>
<h3>职位描述</h3>
<div>
岗位职责: <br>1. 负责公司数据管理制度、规范、流程的设计,参与数据开发平台的建设和管理<br>2. 规划数据仓库工作方向,持续提升团队工作目标和工作效率<br>3. 负责全面了解公司业务,进行深层次的数据分析,为数据开发项目提供指导性的意见,从数据角度为公司产品开发、业务运营提供决策支持建议<br>4. 掌握业界技术动向,组织研究大数据相关前沿技术,用于指导实际的数据支持项目<br>任职要求:<br>1. 精通数据仓库实施理论,生命周期管理,具备大型互联网数据仓库架构设计、模型设计、ETL设计经验,以及海量数据处理和优化经验<br>2. 深入理解Hadoop/Hive/Spark/Storm/Kylin等大数据相关技术和原理<br>3. 有实际使用Hive/MR/Spark等大数据处理技术解决大数据相关问题的项目经验,具备丰富的性能调优经验<br>4 熟悉OLAP工具和数据分析技能,对数据敏感,能够进行数据分析,挖掘数据价值<br>5. 逻辑思维能力强,有较强的学习能力和创新思维,能够解决复杂的商业问题<br>6. 优秀的沟通能力和文字表达能力,有较强的团队管理能力
</div>
</div>
"""
# 清除HTML标签(`/?`:`/`出现0次或者1次)
re.sub(r"</?\w+>|\n| ","",html_str).strip()
# 贪婪演示
# 贪婪模式下会尽可能匹配:
input_str = "我叫小明,欢迎拨打客服:4006789678"
ret = re.match(r"(.+)(\d+)", input_str)
print("[提取的号码为:]",ret.group(2))
print("[贪婪的字符串:]",ret.group(1))
# 解决方法 .+? or .*?
ret = re.match(r"(.+?)(\d+)", input_str)
print("[提取的号码为:]",ret.group(2))
print("[贪婪的字符串:]",ret.group(1))
# 练手小案例
# 加强版提取案例 ~ BOSS
html_str = """
<div class="detail-content">
<div class="job-sec">
<h3>职位描述</h3>
<div class="text">
岗位职责: <br>1. 负责公司数据管理制度、规范、流程的设计,参与数据开发平台的建设和管理<br>2. 规划数据仓库工作方向,持续提升团队工作目标和工作效率<br>3. 负责全面了解公司业务,进行深层次的数据分析,为数据开发项目提供指导性的意见,从数据角度为公司产品开发、业务运营提供决策支持建议<br>4. 掌握业界技术动向,组织研究大数据相关前沿技术,用于指导实际的数据支持项目<br>任职要求:<br>1. 精通数据仓库实施理论,生命周期管理,具备大型互联网数据仓库架构设计、模型设计、ETL设计经验,以及海量数据处理和优化经验<br>2. 深入理解Hadoop/Hive/Spark/Storm/Kylin等大数据相关技术和原理<br>3. 有实际使用Hive/MR/Spark等大数据处理技术解决大数据相关问题的项目经验,具备丰富的性能调优经验<br>4 熟悉OLAP工具和数据分析技能,对数据敏感,能够进行数据分析,挖掘数据价值<br>5. 逻辑思维能力强,有较强的学习能力和创新思维,能够解决复杂的商业问题<br>6. 优秀的沟通能力和文字表达能力,有较强的团队管理能力
</div>
</div>
<div class="job-sec">pass</div>
<div class="job-sec">xx</div>
<div class="job-sec company-info"pass</div>
<div class="job-sec">pass</div>
</div>
"""
# 先找到第一个job-sec(正则思路:直接定位匹配,写几个关键词,其他都是偷懒写法.*?)
ret = re.search(r‘<div.*?job-sec">.*?text">(.*?)</div>‘, html_str, re.S)
new_str = ret.group(1)
print(new_str)
# 再处理下多余的HTML标签
re.sub(r"<br>|\s","",new_str)
# 再来一例 ~ 拉勾
html_str = """
<dd class="job_bt">
<h3 class="description">职位描述:</h3>
<div>
<p>岗位职责:<br>1. 为政企客户和合作伙伴提供腾讯互联网+整体解决方案技术层面的售前架构咨询服务; <br>2. 为政府、企业提供腾讯大数据等项目的规划、咨询服务,协助合作伙伴及产品部门进行大数据等项目的落地; <br>3. 配合BD等团队发展生态合作伙伴,将腾讯能力与合作伙伴方案进行方案融合,为合作伙伴提供咨询、培训、方案融合服务; <br>4. 针对客户互联网+需求,深度定制互联网+解决方案并制定实施计划,把握全局项目进度,协调相关资源、协助实施团队完成方案Demo系统搭建,PoC测试及项目落地工作; <br>5. 负责互联网+案例、技术方案的更新维护,以及布道工作。</p>
<p><br>岗位要求:<br>1. 本科以上学历,5年(硕士3年)以上大数据等售前咨询相关的工作经验; <br>2. 熟悉Hadoop、Spark等开源大数据技术体系,熟悉Oracle、PostgreSQL等数据库。要求至少有3个以上政企大数据项目规划与落地经验; <br>3. 具有宏观思维,有高层汇报能力。熟悉医疗、公安等行业大数据优先; <br>4. 具备优秀的文档能力,清晰明了地表达架构意图,能够熟练编写各类技术文档; <br>5. 良好的沟通、协调及资源整合能力; <br>6. 有针对行业ISV的渠道支持经验优先。</p>
</div>
</dd>
"""
# 匹配需要的内容(正则思路:快速定位,然后.*?偷懒写法走起)
ret = re.search(‘<h3.*?p>(.*?)</p>.*?p>(.*?)</p>‘,html_str,re.S)
# 再处理下多余的HTML标签
for item in (ret.group(1),ret.group(2)):
print(re.sub(r"\s| |<br>", "", item))
第一阶段并发、网络、爬虫、DB的网撒完了,现在准备慢慢收网
这几个系列相关性挺强,随便深入哪一个专题都得扯到其他专题
所以最后网子就有点大了,不过不用慌,慢慢来~
相关系列文章如下:
Python3 与 C# 并发编程之~ 上篇(Net专栏)
Queue引入篇 [看看就行]
线程篇之~加强篇收尾(Event、Timer、Barrier)
标签:print ret 表达式 挖掘 掌握 poc dea 单词 test
原文地址:https://www.cnblogs.com/dotnetcrazy/p/10011135.html