1.网络爬虫概念

说明:网络爬虫就是从互联网中定向或者不定向的采集信息的一种程序。网络爬虫有很多类型:通用网络爬虫、聚焦网络爬虫等等
应用:
(1)搜索引擎
(2)采集金融数据
(3)采取商品信息
(4)自动过滤广告
(5)采集信息,进行相关数据分析等等

2.正则表达式

说明:要用正则表达式,要导入模块import re

2.1 原子

说明:是正则表达式中最基本的单位,每个正则表达式中至少要包含一个原子,常见的原子有:普通字符作为原子、非打印字符作为原子,通用字符作为原子、原子表四类。

  1. 普通字符作为原子

    import re
    str = 'Hello123Python!'
    pat = '123'     #pat为正则表达式
    result = re.search(pat, str)
    print(result)
    # 结果:<re.Match object; span=(5, 8), match='123'>
    
  2. 非打印字符作为原子:
    ① 换行符:\n
    ② 制表符:\t
    ③ 回车符:\r
    等等

    import re
    str = 'Hello123Python!'
    pat2 = '\n'
    print(re.search(pat2, str))
    # 结果:None
    
  3. 通用字符作为原子

    • \w 字母、数字、下划线
    • \W 非字母、数字、下划线
    • \d 十进制数
    • \D 非十进制数
    • \s 匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
    • \S 匹配任何可见字符。等价于[^ \f\n\r\t\v]。
    import re
    str = 'Hello123Python!'
    pat3 = '\w\d\d'
    print(re.search(pat3, str))
    
    # 结果:<re.Match object; span=(4, 7), match='o12'>
    
  4. 原子表:

    1. [一个或多个原子],这表示一个原子表,匹配时从中选一个符合要求的原子,只能匹配一个字母;若没有,返回None
    2. 还可以通过[^一个或多个原子]进行取反,表示除了原子表中的元素都可以提取,也只能匹配一个字符
    3. [a-z]:匹配a到z的字符,也只能匹配一个字符
      [^a-z]:匹配a到z的非字符,也只能匹配一个字符
      [0-9]:匹配0到9的数字,也只能匹配一个字符
    import re
    str = 'Hello123Python!'
    
    pat4 = '\w[139]\d'  
    print(re.search(pat4, str))
    # 结果:<re.Match object; span=(4, 7), match='o12'>
    
    pat5 = 'l[^alo]'           #表示除了原子表[alo]内的元素外我都可以提取
    print(re.search(pat5, str))
    # 结果:None
    

2.2 元字符

说明:元字符就是正则表达式中具有一些特殊含义的字符

  1. .表示 \n\r 以外的任何一个字符
    • 如果想匹配任意字符,则可以使用[\s\S]
  2. ^表示后一个原子处于开始位置
  3. $表示前一个原子处于结束位置
  4. *表示前面的原子接着出现01多次
  5. ?表示前面的原子接着出现01
  6. +表示前面的原子接着出现1多次
  7. {n}表示前面一个原子出现恰好n次(操作时n用具体的数字代替)
  8. {n,}表示前面一个原子出现至少n次
  9. {n, m}表示最少匹配 n 次且最多匹配 m 次
  10. |表示模式选择或
    1. 直接使用:"\da|\db"表示为\da\db
    2. 搭配原子表使用:此时最小匹配单元不再是原子,而是或元素。比如,[.com|.cn]表示为.com.cn
  11. ()表示模式单元
    1. re.findall(正则表达式, 数据)中表示正则表达式匹配之后,只提取模式单元部分
      import re
      
      str = 'HelloPythonHeeeo!'
      pat = 'H(.*?)o'     #懒惰模式
      result = re.findall(pat, str)
      print(result)
      # 输出:['ell', 'eee'] 而不是输出['Hello', 'Heeeo']
      
      还可以搭配|使用,比如H(ell|eee)o
      import re
      
      str = 'HelloPythonHeeeo!'
      pat = 'H(ell|eee)o'
      result = re.findall(pat, str)
      print(result)
      # 输出:['ell', 'eee']
      
    2. re.split(正则表达式的分隔符, 数据)中会提取分隔符本身
      import re
      
      str = 'a&1b&2c&3d'
      pat = '(&\d)'
      result = re.split(pat, str)
      print(result)
      # 输出:['a', '&1', 'b', '&2', 'c', '&3', 'd']
      

整体案例:

import re
str = 'Hello1ooo123Python!'

pat = '^He..'     #pat为正则表达式
result = re.search(pat, str)
print(result)

pat2 = '..on!$'     #pat2为正则表达式
result = re.search(pat2, str)
print(result)

pat3 = '1o*'     #pat3为正则表达式
result = re.search(pat3, str)
print(result)

pat4 = 'e.*'     #pat4为正则表达式
result = re.search(pat4, str)
print(result)

pat5 = '1o{4}'     #pat5为正则表达式
result = re.search(pat5, str)
print(result)

pat6 = 'o(\d*?)P'
result = re.compile(pat6).findall(str)
print(result)

#结果:
<re.Match object; span=(0, 4), match='Hell'>
<re.Match object; span=(14, 19), match='thon!'>
<re.Match object; span=(5, 9), match='1ooo'>
<re.Match object; span=(1, 19), match='ello1ooo123Python!'>
None
['123']

2.3 模式修正符

  • 字母I 匹配时忽略大小写
  • 字母S.能够匹配换行符
  • 字母M 多行匹配
  • 字母U unicode
  • 字母L 本地化识别匹配

注意:以上字母必须为大写
eg:

import re
str = 'Hello1ooo123Python!'

pat = 'hell'     #pat为原子
result = re.search(pat, str, re.I)
print(result)

str = '''Hello1ooo
123Python!'''
pat = 'oo.1'     #pat为原子
result = re.search(pat, str, re.S)
print(result)

#结果:
<re.Match object; span=(0, 4), match='Hell'>
<re.Match object; span=(7, 11), match='oo\n1'>

2.4 贪婪模式、懒惰模式、无限匹配

说明:

  • 贪婪模式就是尽可能多的匹配,语法.*\d*等等,就是元字符或原子与符号*的组合
  • 懒惰模式就是尽可能少的匹配,语法.*?\d*?等等,就是元字符或原子与符号*?的组合
  • [\s\S].*[\d\D].*[\w\W].* 都可以无限匹配,包括换行符

eg:

import re

str = 'HelloPython!'
pat = 'H.*o'     #贪婪模式
pat2 = 'H.*?o'     #懒惰模式
result = re.search(pat, str)
result2 = re.search(pat2, str)
print(result)
print(result2)

#结果:
<re.Match object; span=(0, 10), match='HelloPytho'>
<re.Match object; span=(0, 5), match='Hello'>

3. 正则函数

3.1 查找

  1. re.match()函数,对数据 从头开始匹配,返回字符串所在位置[ab b) 左闭右开,结果只有一个

    import re
    
    str = 'HelloPython!'
    pat = 'H.*?o'     #懒惰模式
    print(re.match(pat, str)) 
    # 输出:<re.Match object; span=(0, 5), match='Hello'>
    
    pat = 'Python'
    print(re.match(pat, str))
    # 输出:None
    
  2. re.search()函数,任意位置匹配,返回字符串所在位置,结果只有一个

    import re
    
    str = 'HelloPython!'
    pat = 'Python'
    print(re.search(pat, str)) 
    # 输出:<re.Match object; span=(5, 11), match='Python'>
    

3.2 提取

  1. re.findall(正则表达式, 数据):函数,任意位置匹配,全局匹配,结果是一个list

    import re
    
    str = 'HelloPythonHeeeo!'
    pat = 'H.*?o'     #懒惰模式
    result = re.findall(pat, str)
    print(result)
    # 输出:['Hello', 'Heeeo']
    

3.3 替换

  1. re.sub(正则表达式, 字符串, 数据)函数,任意位置匹配,用指定的字符串代替匹配到的字符串,全部替换
    import re
    
    str = 'HelloPythonHeeeo!'
    pat = 'H.*?o'     #懒惰模式
    result = re.sub(pat, 'x', str)
    print(result)
    # 输出:xPythonx!
    

3.4 切分

  1. re.split(正则表达式的分隔符, 数据):使用分隔符切分数据,返回一个list
    import re
    
    str = 'a&1b&2c&3d'
    pat = '&\d'
    result = re.split(pat, str)
    print(result)
    # 输出:['a', 'b', 'c', 'd']
    

3. 案例

3.1 实例之匹配.com.cn网址

eg:

import re

str = '<a href=http://www.baidu.com>百度首页</a>'
#[a-zA-Z]表示从a到z和A到Z的所有字母
#|为模式选择或   [.com|.cn]表示为.com或.cn
pat = '[a-zA-Z]+://[^\s]*[.com|.cn]'
print(re.compile(pat).findall(str))

#结果:
['http://www.baidu.com']

3.2 实例之匹配电话号码

说明:电话号码有两种

  • 前3位为域名+后8位
  • 前4位为域名+后7位

eg:

import re

str = 'dsadasdgs031-1564653233adads2312-24644567dZDxz'
pat = '\d{3}-\d{8}|\d{4}-\d{7}'
print(re.compile(pat).findall(str))

#结果:
['031-15646532', '2312-2464456']

3.3 实战之爬取网址上的QQ号

eg:爬取该网址内的QQ号

#简单爬虫编写,自动爬取上面两个QQ号
import urllib.request
import re
data = urllib.request.urlopen("https://www.yiibai.com/python3").read().decode("utf-8") #decode()函数是设置读取编码格式
pat = 'QQ群:(\d*)'
result = re.compile(pat).findall(data)
print(result)
#结果:
['227270512', '479429477']
    
#简单爬虫编写,自动爬取该网页所有QQ群
import urllib.request
import re
data = urllib.request.urlopen("https://www.yiibai.com/python3").read().decode("utf-8") #decode()函数是设置读取编码格式
pat = '[1-9]{6,10}'
result = re.compile(pat).findall(data)
# 去除重复的QQ号
result = list(set(result))
print('该网站共有'+str(len(result))+'个QQ群:')
print(result)
# 结果:
该网站共有17个QQ群:
['769728683', '65515455', '5798217', '415553199', '1932146371', '6215498', '175248146', '9485766451', '944874', '6494738921', '456236', '816911', '629264796', '153241', '397883996', '479429477', '851549']
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐