zoukankan      html  css  js  c++  java
  • 网罗天下之~正则表达

     

    正则表达

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

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

    1.单个字符

    字符含义
    . 匹配任意1个字符(除了
    [] 匹配[ ]中列举的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=' '>
      • 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","	")
    # 回车匹配验证
    my_match("s","
    ")
    
    # 不匹配验证:(空字符串)
    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","滚")
    
    # .匹配任意字符,不包括
    的验证:
    my_match(".","
    ")
    
    # 除了
    ,可以匹配任意一个字符
    my_match(".","	")
    
     
    [匹配结果:滚]
    [
    不匹配]
    [匹配结果:	]
    
    Out[6]:
    <re.Match object; span=(0, 1), match='	'>
    In [7]:
    # 扩展
    
    # 如果想让.支持
    ,再多传个flag:re.S
    re.match(".","
    ",re.S)
    
    Out[7]:
    <re.Match object; span=(0, 1), match='
    '>
     

    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 匹配非单词的边界
    ( ) 将括号中字符作为一个分组
    um 引用分组num匹配到的字符串
    (?P<name>) 分组起别名
    (?P=name) 引用别名为name分组匹配到的字符串
    In [17]:
    # 匹配边界
    
    #  匹配以net结尾的单词
    my_match(r"w+net","dotnet")
    my_match(r"w+net","dotnet crazy")
    
    # 不匹配验证
    my_match(r"w+net","dotnetcrazy")
    
    # 后面会讲
    re.findall(r"w+net","dotnet crazy aspnet")
    
     
    [匹配结果:dotnet]
    [匹配结果:dotnet]
    [dotnetcrazy不匹配]
    
    Out[17]:
    ['dotnet', 'aspnet']
    In [18]:
    # 不匹配验证:、B、^、$只是代表边界,并不表示空格
    my_match(r"w+net","dot net crazy")
    
    # 正确修改
    my_match(r"w+snet","dot net crazy")
    
    # 把上面换成B,则代表单词间必须是 非空格的字符
    my_match(r"w+BnetB","dotnetcrazy")
    my_match(r"w+BnetB","dotnetAcrazy")
    my_match(r"w+BnetB","dotnet1crazy")
    
    # 不匹配验证
    my_match(r"w+BnetB","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"4001","我是小明,客服电话是: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+>|
    | ","",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专题

    并发编程~协程引入篇

  • 相关阅读:
    如何在 Microsoft Visual C# .NET 中实现 Microsoft Excel 自动化
    CentOS 6.5静态IP的设置(NAT和桥接都适用)
    myeclipse里如何添加mysql数据库
    Attribute value is quoted with " which must be escaped when used within the value 问题解决
    CentOS 6.5安装之后的网络配置
    Apache server for win解压版的安装与配置
    Oracle SQL 基本操作之 用户权限管理方法
    CentOS 6.5的安装详解
    IO类01
    可见性的问题
  • 原文地址:https://www.cnblogs.com/dotnetcrazy/p/10011135.html
Copyright © 2011-2022 走看看