网罗天下之~正则表达

 

正则表达

微信阅读:网罗天下之~正则表达

在线预览:http://github.lesschina.com/python/spider/re/1.网罗天下之-正则表达.html

1.单个字符

字符含义
. 匹配任意1个字符(除了\n
[] 匹配[ ]中列举的1个字符(^可以取反)
\d 匹配数字(0~9
\D 匹配非数字(非数字
\s 匹配空白(空格、Tab键、回车
\S 匹配非空白
\w 匹配单词字符,即a-z、A-Z、0-9、_(包括单个中文字符)
\W 匹配非单词字符

注意:

  1. \s并不匹配""
  2. <re.Match object; span=(0, 1), match='\t'>
    • PS:match=xxx,就是我们ret.group()的结果
In [1]:
# 定义一个通用测试方法
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 表示原生字符串(不转义)
In [2]:
# \s 验证

# 空格匹配验证
my_match("\s"," ")
# Tab键匹配验证
my_match("\s","\t")
# 回车匹配验证
my_match("\s","\n")

# 不匹配验证:(空字符串)
my_match("\s","")
 
[匹配结果: ]
[匹配结果:	]
[匹配结果:
]
[不匹配]
In [3]:
# \d 验证

# 匹配单个数字
my_match("\d","1") # 一点要变成字符串

# 多个数字则只能匹配一个字符
my_match("\d","11") # 注意

# 解决:以^开头,以$结尾
my_match("^\d$","11")
 
[匹配结果:1]
[匹配结果:1]
[11不匹配]
In [4]:
# [] 验证

# 不是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]","_")
 
[4不匹配]
[匹配结果:7]
[5不匹配]
[匹配结果:7]
[匹配结果:b]
[匹配结果:B]
[_不匹配]
In [5]:
# [] 取反扩展
# \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")
 
[匹配结果:3]
[匹配结果:@]
[4不匹配]
[匹配结果:7]
[匹配结果:#]
[5不匹配]
In [6]:
# \w在UTF8下会匹配中文的验证:
my_match("\w","滚")

# .匹配任意字符,不包括\n的验证:
my_match(".","\n")

# 除了\n,可以匹配任意一个字符
my_match(".","\t")
 
[匹配结果:滚]
[
不匹配]
[匹配结果:	]
Out[6]:
<re.Match object; span=(0, 1), match='\t'>
In [7]:
# 扩展

# 如果想让.支持\n,再多传个flag:re.S
re.match(".","\n",re.S)
Out[7]:
<re.Match object; span=(0, 1), match='\n'>
 

2.多个字符

字符含义
* 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") # 下面有案例
In [8]:
# * 、 + 、?

# *: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")
 
[匹配结果:]
[匹配结果:11]
[不匹配]
[匹配结果:1]
[匹配结果:11]
[11不匹配]
[匹配结果:]
[匹配结果:1]
Out[8]:
<re.Match object; span=(0, 1), match='1'>
In [9]:
# 为什么用^和$包裹,看下面两个奇葩案例就知道了

my_match("\d","123333")

my_match("\d*","a") # ==> "a" ==> """a"
 
[匹配结果:1]
[匹配结果:]
Out[9]:
<re.Match object; span=(0, 0), match=''>
In [10]:
# {}指定位数验证
# ? ==> {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")
 
[匹配结果:7]
[匹配结果:17]
[777不匹配]
[匹配结果:1234567890]
[123456789不匹配]
[A123456789不匹配]
In [11]:
# {} 扩展
# * ==> {0,}
# + ==> {1,}

# \d 至少3个
my_match(r"\d{3,}","123")
my_match(r"\d{3,}","1234")
# 错误验证
my_match(r"\d{3,}","12")
 
[匹配结果:123]
[匹配结果:1234]
[12不匹配]
In [12]:
# ^ $ 案例

# 验证变量命名
my_match(r"^[a-zA-z_]\w*$","a_bbp")
my_match(r"^[a-zA-z_]\w*$","_")
 
[匹配结果:a_bbp]
[匹配结果:_]
Out[12]:
<re.Match object; span=(0, 1), match='_'>
In [13]:
# 测试一个就知道为什么用\w了
def test蛋():
    print("mmd")

test蛋() # Python Code
 
mmd
In [14]:
# 如果没有加开头和结尾的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")
 
[匹配结果:a_b]
[匹配结果:mmd@qq.com]
[a_b#w不匹配]
In [15]:
# 转义字符 \ 引入案例

# 测试Bug,这个也匹配了
my_match(r"[a-zA-z_]+@qq.com","mmd@qq#comcom")

# 改进 ~ 现在不匹配了 (开头结尾+\转义)
my_match(r"^[a-zA-z_]+@qq\.com$","mmd@qq#comcom")
 
[匹配结果:mmd@qq#com]
[mmd@qq#comcom不匹配]
In [16]:
# r"",如果包含转义字符\就容易出错了,这时候r""就上场了
try:
    my_match("\\mmd","\mmd")
except Exception as ex:
    print(ex)

# 原因分析
# \是有特殊含义的,想要没有特殊含义就再加个\,
# 那加上的这个\又有特殊含义,所以就蛋疼了,r""这时候就上场了

# 解决方法
my_match(r"\\mmd", "\\mmd")
 
bad escape \m at position 0
[匹配结果:\mmd]
Out[16]:
<re.Match object; span=(0, 4), match='\\mmd'>
 

3.其他字符

字符含义
| 匹配左右任意一个表达式
\b 匹配一个单词的边界(字母与空格间的位置)
\B 匹配非单词的边界
( ) 将括号中字符作为一个分组
\num 引用分组num匹配到的字符串
(?P<name>) 分组起别名
(?P=name) 引用别名为name分组匹配到的字符串
In [17]:
# 匹配边界

# \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")
 
[匹配结果:dotnet]
[匹配结果:dotnet]
[dotnetcrazy不匹配]
Out[17]:
['dotnet', 'aspnet']
In [18]:
# 不匹配验证:\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")
 
[dot net crazy不匹配]
[匹配结果:dot net]
[匹配结果:dotnet]
[匹配结果:dotnet]
[匹配结果:dotnet]
[dotnet#crazy不匹配]
In [19]:
# | 匹配左右任意一个表达式

# 匹配小明或者小张
my_match(r"^小明|小张$","小明")
my_match(r"^小明|小张$","小张")
# 不匹配验证
my_match(r"^小明|小张$","小潘")
 
[匹配结果:小明]
[匹配结果:小张]
[小潘不匹配]
In [20]:
# () 将括号中字符作为一个分组

# 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)
 
[匹配结果:mmd@163.com]
[匹配结果:<h1>萌萌哒</h1>]
Out[20]:
'h1'
In [21]:
# groups返回所有的匹配结果
my_match(r"^<([a-zA-Z1-9]+)><([a-zA-Z1-9]+)>(.*)</\2></\1>$","<p><font>我去</font></p>").groups()
 
[匹配结果:<p><font>我去</font></p>]
Out[21]:
('p', 'font', '我去')
In [22]:
# 匹配 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")
 
[匹配结果:mmd@qq.com]
('mmd', 'qq')
[匹配结果:mmd@163.com]
('mmd', '163')
[@163.com不匹配]
[mmd@123.com不匹配]
In [23]:
# 别名案例(不常用)
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>")
 
[匹配结果:<html><h1>萌萌哒</h1></html>]
[<html><h1>萌萌哒</h2></html>不匹配]
In [24]:
# 练练手
In [25]:
# 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")
 
[0不匹配]
[匹配结果:7]
[匹配结果:77]
[07不匹配]
[777不匹配]
[匹配结果:0]
[匹配结果:1]
[匹配结果:70]
[匹配结果:100]
[07不匹配]
[170不匹配]
[700不匹配]
 

4.Python扩展

上面的都是通用系列,下面的才能体现为啥爬虫是Python的优势:

  1. re.match:和其他语言用法一致(默认从头开始匹配)
  2. re.search:匹配第一个并返回(如果加了^$就和match一样了)
  3. re.findall:返回所有匹配的列表
  4. re.sub:将匹配到的数据进行替换,再返回新的字符串
    • 匹配之后替换成默认值
    • 匹配之后进行函数处理
  5. re.split:正则切割函数(类似于字符串的split)
  6. re.compile:正则字符串编译成正则表达式对象
In [26]:
# 匹配第一个就结束了
ret = re.search(r"\d","我的名字叫小明,今年23,88")
print(ret.group())

# 如果加了开头结尾就和match一样了
print(re.search(r"^\d$","我的名字叫小明,今年23,88"))
 
2
None
In [27]:
# 返回所有匹配的列表
re.findall(r"\d","我的名字叫小明,今年23,88")
Out[27]:
['2', '3', '8', '8']
In [28]:
re.split(r",|。","我的名字叫小明,今年23。88")
Out[28]:
['我的名字叫小明', '今年23', '88']
In [29]:
# sub案例:批量替换1
re.sub(r"\d+","***","我上次买的时候98.5块,现在30就拿到了,差评!")
Out[29]:
'我上次买的时候***.***块,现在***就拿到了,差评!'
In [30]:
# sub案例:批量替换2 ~ 拿到分组内容并进行处理
re.sub(r"(\d+)",r"400\1","我是小明,客服电话是:6789688")
Out[30]:
'我是小明,客服电话是:4006789688'
In [31]:
# sub案例:函数处理
def shit_test(result):
    # 返回类型必须是str
    return str(float(result.group())*2)

re.sub(r"\d+",shit_test,"我上次买的时候98.5块,现在30就拿到了,差评!")
Out[31]:
'我上次买的时候196.0.10.0块,现在60.0就拿到了,差评!'
In [32]:
# 扩展内容

pattern = re.compile(r"A.*Z",re.S) # 表达式复用

print(re.match(pattern,"ABZ").group())
print(re.match(pattern,"ACZ").group())
 
ABZ
ACZ
In [33]:
# 练手小案例
In [34]:
# 提取单词
input_str = "Python Golang NetCore JavaScript"

print(re.split(" ",input_str))

re.findall("[a-zA-Z]+",input_str)
 
['Python', 'Golang', 'NetCore', 'JavaScript']
Out[34]:
['Python', 'Golang', 'NetCore', 'JavaScript']
In [35]:
# 提取文字 """ 保留字符串原始格式
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()
Out[35]:
'职位描述岗位职责:1.负责公司数据管理制度、规范、流程的设计,参与数据开发平台的建设和管理2.规划数据仓库工作方向,持续提升团队工作目标和工作效率3.负责全面了解公司业务,进行深层次的数据分析,为数据开发项目提供指导性的意见,从数据角度为公司产品开发、业务运营提供决策支持建议4.掌握业界技术动向,组织研究大数据相关前沿技术,用于指导实际的数据支持项目任职要求:1.精通数据仓库实施理论,生命周期管理,具备大型互联网数据仓库架构设计、模型设计、ETL设计经验,以及海量数据处理和优化经验2.深入理解Hadoop/Hive/Spark/Storm/Kylin等大数据相关技术和原理3.有实际使用Hive/MR/Spark等大数据处理技术解决大数据相关问题的项目经验,具备丰富的性能调优经验4熟悉OLAP工具和数据分析技能,对数据敏感,能够进行数据分析,挖掘数据价值5.逻辑思维能力强,有较强的学习能力和创新思维,能够解决复杂的商业问题6.优秀的沟通能力和文字表达能力,有较强的团队管理能力'
 

5.贪婪模式

正则表达式默认就是贪婪模式,只要符合表达式就尽可能去匹配(eg:.+.*

解决方法:后面加个?(eg:.+?.*?

In [36]:
# 贪婪演示

# 贪婪模式下会尽可能匹配:
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))
 
[提取的号码为:] 8
[贪婪的字符串:] 我叫小明,欢迎拨打客服:400678967
[提取的号码为:] 4006789678
[贪婪的字符串:] 我叫小明,欢迎拨打客服:
In [37]:
# 练手小案例
In [38]:
# 加强版提取案例 ~ 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)
 
        岗位职责: <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. 优秀的沟通能力和文字表达能力,有较强的团队管理能力
        
Out[38]:
'岗位职责:1.负责公司数据管理制度、规范、流程的设计,参与数据开发平台的建设和管理2.规划数据仓库工作方向,持续提升团队工作目标和工作效率3.负责全面了解公司业务,进行深层次的数据分析,为数据开发项目提供指导性的意见,从数据角度为公司产品开发、业务运营提供决策支持建议4.掌握业界技术动向,组织研究大数据相关前沿技术,用于指导实际的数据支持项目任职要求:1.精通数据仓库实施理论,生命周期管理,具备大型互联网数据仓库架构设计、模型设计、ETL设计经验,以及海量数据处理和优化经验2.深入理解Hadoop/Hive/Spark/Storm/Kylin等大数据相关技术和原理3.有实际使用Hive/MR/Spark等大数据处理技术解决大数据相关问题的项目经验,具备丰富的性能调优经验4熟悉OLAP工具和数据分析技能,对数据敏感,能够进行数据分析,挖掘数据价值5.逻辑思维能力强,有较强的学习能力和创新思维,能够解决复杂的商业问题6.优秀的沟通能力和文字表达能力,有较强的团队管理能力'
In [39]:
# 再来一例 ~ 拉勾

html_str = """
<dd class="job_bt">
        <h3 class="description">职位描述:</h3>
        <div>
        <p>岗位职责:<br>1. 为政企客户和合作伙伴提供腾讯互联网+整体解决方案技术层面的售前架构咨询服务;&nbsp;<br>2. 为政府、企业提供腾讯大数据等项目的规划、咨询服务,协助合作伙伴及产品部门进行大数据等项目的落地;&nbsp;<br>3. 配合BD等团队发展生态合作伙伴,将腾讯能力与合作伙伴方案进行方案融合,为合作伙伴提供咨询、培训、方案融合服务;&nbsp;<br>4. 针对客户互联网+需求,深度定制互联网+解决方案并制定实施计划,把握全局项目进度,协调相关资源、协助实施团队完成方案Demo系统搭建,PoC测试及项目落地工作;&nbsp;<br>5. 负责互联网+案例、技术方案的更新维护,以及布道工作。</p>
<p><br>岗位要求:<br>1. 本科以上学历,5年(硕士3年)以上大数据等售前咨询相关的工作经验;&nbsp;<br>2. 熟悉Hadoop、Spark等开源大数据技术体系,熟悉Oracle、PostgreSQL等数据库。要求至少有3个以上政企大数据项目规划与落地经验;&nbsp;<br>3. 具有宏观思维,有高层汇报能力。熟悉医疗、公安等行业大数据优先;&nbsp;<br>4. 具备优秀的文档能力,清晰明了地表达架构意图,能够熟练编写各类技术文档;&nbsp;<br>5. 良好的沟通、协调及资源整合能力;&nbsp;<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|&nbsp;|<br>", "", item))
 
岗位职责:1.为政企客户和合作伙伴提供腾讯互联网+整体解决方案技术层面的售前架构咨询服务;2.为政府、企业提供腾讯大数据等项目的规划、咨询服务,协助合作伙伴及产品部门进行大数据等项目的落地;3.配合BD等团队发展生态合作伙伴,将腾讯能力与合作伙伴方案进行方案融合,为合作伙伴提供咨询、培训、方案融合服务;4.针对客户互联网+需求,深度定制互联网+解决方案并制定实施计划,把握全局项目进度,协调相关资源、协助实施团队完成方案Demo系统搭建,PoC测试及项目落地工作;5.负责互联网+案例、技术方案的更新维护,以及布道工作。
岗位要求:1.本科以上学历,5年(硕士3年)以上大数据等售前咨询相关的工作经验;2.熟悉Hadoop、Spark等开源大数据技术体系,熟悉Oracle、PostgreSQL等数据库。要求至少有3个以上政企大数据项目规划与落地经验;3.具有宏观思维,有高层汇报能力。熟悉医疗、公安等行业大数据优先;4.具备优秀的文档能力,清晰明了地表达架构意图,能够熟练编写各类技术文档;5.良好的沟通、协调及资源整合能力;6.有针对行业ISV的渠道支持经验优先。

 

第一阶段并发、网络、爬虫、DB的网撒完了,现在准备慢慢收网

这几个系列相关性挺强,随便深入哪一个专题都得扯到其他专题

所以最后网子就有点大了,不过不用慌,慢慢来~

相关系列文章如下: 

聊聊数据库-概念

聊聊数据库~开篇

 

万物互联之~网络基础

网络编程~UDP专题

网络编程~TCP专题

万物互联之~网络加强

 

1.并发编程~先导篇(上)

2.并发编程~先导篇(下)

Python3 与 C# 并发编程之~ 上篇(Net专栏)

Python3 与 C# 并发编程之~ 进程篇上

Python3 与 C# 并发编程之~ 进程篇中

Python3 与 C# 并发编程之~ 进程篇下

Python3 与 C# 并发编程之~ 进程实战篇

 

Python3 与 C# 并发编程之~ 线程入门篇

Python3 与 C# 并发编程之~ 线程篇-锁专题

线程篇之~锁专题扩展

线程篇之~线程安全篇

Queue引入篇 [看看就行]

线程篇之~Queue专题

线程篇之~Queue扩展篇

线程篇之~加强篇收尾(Event、Timer、Barrier)

线程深入篇~引子

线程深入篇之~GIL专题

线程篇~Actor专题

 

并发编程~协程引入篇

posted @ 2018-11-24 10:10 鲲逸鹏 阅读(...) 评论(...) 编辑 收藏