Python学习-01

237 阅读22分钟

Python基本格式

  • Python中不区分大小写

  • Python中的结构区分采用空格和占位符来标识,没有大括号这种形式。这里需要注意的是占位符和空格数目要相同

  • Python的注释形式

    1. 行内形式: #
    2. 多行注释:三个单引号或者双引号来表示,例如
'''
多行注释
'''
"""
多行注释
"""

基础知识

  • 标识符:用于变量、函数、类、模块等名称

  • 变量名必须以字母开头

  • 标识符不能使用关键字

  • 可通过help() -- keywords查看关键

  • 命名规则

    1. 模块和包名

      全部小写字母,多个单词下划线隔开

    2. 函数名

      全小写字母,多个单词使用下划线隔开

    3. 类名

      首字母大写,采用驼峰状写法

    4. 常量名

      全部大写字母,多个单词使用下划线隔开

赋值

1. 链式赋值

链式赋值用于将同一个对象赋值给多个变量,例如

x=y=30 相当于 x=30; y=30

2. 系列解包赋值

系列数据赋值给多个变量,例如

a,b,c=10,20,30相当于a=10;b=20;c=30

3. 常量

Python不支持常量,只能通过大小写来规定是否为常量,但是依然可以修改

运算符

+ - * /
// 表示整除
** 表示幂
% 求余

格式化字符串

使用%号格式化

word = "整型:%d,浮点型:%.2f,字符串:%s"%(2, 3.346, "Hello World!")
  1. 其中,%.2f 用来格式化浮点型,保存两位小数

使用f格式化

name = "江户川柯南"
age = 7
addr = "日本"
word = f"姓名:{name},年龄:{age},地址:{addr}"
  • {}中的名称需要和变量名一致,类似于mybatis中的写法

使用format格式化

word = "姓名:{},年龄:{},地址:{}".format("工藤新一", 17, "日本")
  1. 用法1:可以使用索引作为占位符
word = "姓名:{0},年龄:{1},人物:{0}".format("工藤新一", 17)
"""
  结果:姓名:工藤新一,年龄:17,人物:工藤新一
"""
  1. 用法2:使用关键字作为占位符
word = "姓名:{name},年龄:{age},人物:{name}".format(name = "工藤新一", age = 17)
"""
  结果:姓名:工藤新一,年龄:17,人物:工藤新一
"""
  1. 用法3:通过对象属性作为占位符
class Person:
   def __init__(self, name, age):
       self.name = name
       self.age = age
   def __str__(self, name, age):
       return 'This guy is {self.name},is {self.age} old'.format(self=self) 

peson = Person("灰原哀", 7)
word = "姓名:{person.name},年龄:{person.age},人物:{person.name}".format(person = peson)
print(word) 
  1. 格式限定符

  • 填充常跟对齐一起使用
  • ^、<、>分别是居中、左对齐、右对齐,后面带宽度
  • :号后面带填充的字符,只能是一个字符,不指定的话默认是用空格填充
word = "名称:{:^10}".format("测试")
print(word)

# 保存两位小数,四舍五入
word = "score:{:.2f}".format(12.34567)
print(word)

判断语句

  1. Python可以指定非0或非空值为true,0或None非false

  2. if控制语句格式如下:

  • 【elif】为其他情况
  • 每个判断条件后需要加冒号
if 判断条件1:
	 执行语句
elif 判断条件2:
	 执行语句
else
   执行语句

循环语句

在循环语句中,可以使用break、continue,pass三种控制循环

  1. break:跳出循环
  2. continue:跳出本次循环
  3. pass:占位符,没有实际意义

for循环

  1. for...i...形式

  • 循环数字
for i in range(10):
	print(i)
  • 自增循环
# 参数1:初始值 参数2:最大范围 参数3:自增
for i in range(1, 10, 2):
	print(i)
  • 循环数组
a = ["aa", "bb", "cc", "dd"]
for i in range(len(a)):
	print(a[i])
  1. foreach形式

  • 循环字符
a = "chengdu"
for i in a:
	print(i)
  • 循环数组
a = ["aa", "bb", "cc", "dd"]
for i in a:
	print(i)

while循环

  • 和其他语言类似情况
a = 0
while a < 5:
  print(a)
  a+=1
  • while中也可以使用else,else:除了break之外的结果循环都会走这个方法
a = 0
while a < 5:
  print(a)
  a+=1
else:
  print("不满足条件")

字符串、列表、元组、字典

可变数据类型:list(列表)、dict(字典)、set(集合,不常用)

不可变数据类型:数值类型(int、float、bool)、string(字符串)、tuple(元组)

字符串

  • Python的核心数据类型
  • Python字符串可以用单引号双引号三引号(三个单引号或三个双引号),使用\表示转义字符

  • 三引号可以保存输入字符串的格式,例如:

    # 输出时可以保存格式
    paragraph = """
          这是一个段落
          可以由多行组成
    """
    
  • 单引号和双引号

  • Python3源码文件默认以UTF-8编码,所有字符都是unicode字符
  • 支持字符串的拼接、截取等多种运算
常用转义字符
转义字符描述
\\反斜杠符号
\'单引号
\"双引号
\n换行
\a响铃
\b退格
\000
\n换行
\t制表符

运算函数

截取字符串
  • 基本形式 str[起始位置:结束位置:步进值],起始位置为开始截取位置(包含该位置)、结束位置(不包含该位置)、步进值(跳着截取长度)
str = "名侦探柯南,柯南:真相只有一个"
print(str)
print(str[0]) # 从0截取,截取一个 结果:名
print(str[0:3]) # 从0开始截取,截取到第3位,结果:名侦探
print(str[1:7:2]) # 从1开始截取,截取到第7位,每次跳2个, 结果位:侦柯,
  • 简写模式
print(str[3:])  # 结束位置为最后
print(str[3:7])
print(str[:7]) # 起始位置为第一位
拼接字符串
  • 使用+号连接 print(str + ",你好")
  • 使用*号连续输出print(str*3),连续输出三次str
  • 使用r可以取消正则表达式功能print(r"江户川柯南\n灰原哀"),\n转义字符不再生效,结果为:江户川柯南\n灰原哀
内置函数
方法描述
capitalize()首字母大写
center(length, word)字符串居中,length表示长度,word表示填充的字符串,不足填充该字符串
count(sub, start, end)统计字符串sub出现的次数,start和end表示统计范围
string.decode(encoding='UTF-8', errors='strict')以 encoding 指定的编码格式解码 string,如果出错默认报一个 ValueError 的 异 常 , 除 非 errors 指 定 的 是 'ignore' 或 者'replace'
string.encode(encoding='UTF-8', errors='strict')以 encoding 指定的编码格式编码 string,如果出错默认报一个ValueError 的异常,除非 errors 指定的是'ignore'或者'replace'
string.endswith(obj, beg=0, end=len(string))检查字符串是否以 obj 结束,如果beg 或者 end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回 False.
string.expandtabs(tabsize=8)把字符串 string 中的 tab 符号转为空格,默认的空格数 tabsize 是 8.
string.find(str, beg=0, end=len(string))检测 str 是否包含在 string 中,如果 beg 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回-1
string.index(str, beg=0, end=len(string))跟 find() 方法一样,只不过如果 str 不在 string 中会报一个异常.
string.isalnum()如果 string 至少有一个字符并且所有字符都是字母或数字则返回 True,否则返回 False
string.isalpha()如果 string 至少有一个字符并且所有字符都是字母则返回 True,否则返回 False
string.isdecimal()如果 string 只包含十进制数字则返回 True 否则返回 False.
string.isdigit()如果 string 只包含数字则返回 True 否则返回 False.
string.islower()如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True,否则返回 False
string.isnumeric()如果 string 中只包含数字字符,则返回 True,否则返回 False
string.isspace()如果 string 中只包含空格,则返回 True,否则返回 False.
string.istitle()如果 string 是标题化的 (见 title()) 则返回 True,否则返回 False
string.isupper()如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True,否则返回 False
string.join(seq)Merges (concatenates)以 string 作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串
string.ljust(width)返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串
string.lower()转换 string 中所有大写字符为小写.
string.lstrip()截掉 string 左边的空格
string.maketrans(intab, outtab])maketrans() 方法用于创建字符映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标。
max(str)返回字符串str 中最大的字母。
min(str)返回字符串str 中最小的字母。
string.partition(str)有点像 find()和 split() 的结合体,从 str 出现的第一个位置起,把 字 符 串 string 分 成 一 个 3 元 素 的 元 组 (string_pre_str,str,string_post_str),如果 string 中不包含str 则 string_pre_str == string.
string.replace(str1, str2, num=string.count(str1))把 string 中的 str1 替换成 str2,如果 num 指定,则替换不超过 num 次.
string.rfind(str, beg=0,end=len(string) )类似于 find()函数,不过是从右边开始查找.
string.rindex( str, beg=0,end=len(string))类似于 index(),不过是从右边开始.
string.rjust(width)返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串
string.rpartition(str)类似于 partition()函数,不过是从右边开始查找.
string.rstrip()删除 string 字符串末尾的空格.
string.split(str="", num=string.count(str))以 str 为分隔符切片 string,如果 num有指定值,则仅分隔 num 个子字符串
string.splitlines(num=string.count('\n'))按照行分隔,返回一个包含各行作为元素的列表,如果 num 指定则仅切片 num 个行.
string.startswith(obj, beg=0,end=len(string))检查字符串是否是以 obj 开头,是则返回 True,否则返回 False。如果beg 和 end 指定值,则在指定范围内检查.
string.strip([obj])在 string 上执行 lstrip()和 rstrip()
string.swapcase()翻转 string 中的大小写
string.title()返回"标题化"的 string,就是说所有单词都是以大写开始,其余字母均为小写(见 istitle())
string.translate(str, del="")根据 str 给出的表(包含 256 个字符)转换 string 的字符,要过滤掉的字符放到 del 参数中

列表

  • List(列表)
  • 列表中可以放不同的数据类型
  • 列表索引值以0开始,-1位末尾的开始位置
  • 列表可以用+号表示拼接,使用*表示重复
  • 支持for...i...和foreach循环语句
nameList = ["柯南", "灰原哀", "原太", "步美", "光彦", 9527]
print(nameList[0])
print(nameList[-1])
print(nameList[len(nameList) - 1])

print(type(nameList[-1]))  # 类型为int,而不会自动转换为字符串

wordList = ["琴酒", "伏特加", "贝尔摩德", "朗伯", 6782]

print(nameList + wordList)  # 数组合并
print(wordList * 3) # 数组重复

内置方法

  • 方法分为增删该查和排序五个主要的操作
操作名称描述举例
【增】append(object)在末尾增加一个元素,可以是数组对象,数组对象作为一个完整的元素存在
【增】extend(object)在末尾扩展,可以是数组对象,如果是数组,则会将数组元素拼接到元素中
【增】insert(index, object)在指定位置添加一个元素
【增】使用+拼接效率相对不高
【删】del删除某个元素del nameList[3]
【删】pop(index)删除指定位置元素name.pop(3)
【删】remove(object)删除指定元素remove("柯南")
【查】in查询元素是否存在"柯南" in nameList
【查】not in查询元素是否不在"柯南" not in nameList
【查】index(object, start, end)可以查询指定范围的元素,返回元素索引,找不到会抛出异常nameList.index("步美", 3, 10)
【查】count(object)查询object出现的次数nameList.count("步美")
【反转】reverse数组反转nameList.reverse()
【排序】sort(option)排序,默认正序,反序时,option为reverse=True,可以不写。排序时数据类型必须一致nameList.sort(reverse=True)

Tuple元祖

  • tuple和list类似,使用小括号表示,多个用逗号隔开
  • 如果仅仅包含一个元素,则必须加逗号
  • 元祖的元素不可变,但是可以包含可变对象,例如list

函数

基本格式

def funciton_name():
	function_body
    return result;
  • return是可选,如果没有返回值,则可以不写,默认返回None
  • 函数返回值可以是任意类型的对象和表达式
  • 函数返回值可以有多个,多个以逗号隔开
def test(name, age):
   name += "姓名:"
   age += 10
   return name, age

# 这里是根据名称进行匹配的
age, name = test("柯南", 7)

# 返回值类型为元组(tuple)
a = test("灰原哀", 17)

print(name, age)
print(a)
print(type(a))

参数分类

  • 从函数定义角度来看,参数分为两种

    1. 必选参数,必须指定

    2. 可选参数,可以指定也可以不指定,不指定时使用默认值

    • 少于必选参数或超过总参数都会出现异常TypeError
def personInfo(name, age, addr = "地球", work = "侦探"):
    return "姓名:{},年龄:{},地址:{},工作:{}".format(name, age, addr, work);

print(personInfo("新一", 17))
print(personInfo("柯南", 7, "帝丹小学","小学生"))
  • 从函数调用角度,参数分为:

  1. 位置参数,即根据位置匹配参数
  2. 关键字参数,即根据关键字匹配参数
def personInfo(name, age, addr = "地球", work = "侦探"):
    return "姓名:{},年龄:{},地址:{},工作:{}".format(name, age, addr, work);

# 调用方式1:
print(personInfo("新一", 17))
print(personInfo("柯南", 7, "帝丹小学","小学生"))

# 调用方式2:
print(personInfo(age = "新一", name = 17))
print(personInfo(work = "柯南", addr = 7, age = "帝丹小学", name = "小学生"))
  • 从参数个数角度,有一类叫可变参数,即参数个数不一定,即0个或任意个。通常用*args**kw表示,也可以用其他名称

  1. *args:参数调用使用位置参数匹配,结果时一个元组类型

  2. **kw:参数调用使用关键字参数匹配,结果为字典类型

  • 可变位置参数需要在必选参数前;可变关键字参数必须在必选参数后,否则会抛出异常
def getPersonName(*a, **b):
   print(a)
   print(b)

getPersonName("1", "2", "3", "4", five = "5", six = "6", senve= "7")

"""
  结果:
('1', '2', '3', '4')
{'five': '5', 'six': '6', 'senve': '7'}
"""
def getUsers(**b):
   print(b)

getUsers("2", "3")

"""
这里由于仅仅定义了关键字匹配参数,而传入了位置匹配的参数,因此会抛出异常
"""

注:函数参数传递的是实际对象的内存地址。如果参数是引用类型的数据类型(列表、字典等),在函数内部修改后,就算没有把修改后的值返回回去,外面的值其实也已经发生了变化。

匿名函数

func = lambda **prams: print(prams) 
print(func(name = "测试", sex = "男", age = 17))

反射函数

学习python模块入口

  • 在console模式下,输入help(),可以进入help模式,在该模式下,可以查看内置函数和类型的使用方法

变量的作用域

Python中的作用域可以分为四种:

  1. 局部作用域
  2. 闭包
  3. 全局作用域
  4. 内建作用域

:star: 全局作用域

在python中,不可以直接修改函数外的变量的值,可以通过global来修改(这里的修改,其实是一个新的变量,变量地址变了)

age = 10
print(id(age))

def add():
   global age
   age += 11
   print(id(age))
   return age

print(add())

闭包函数

  1. 如果一个内函数包裹在另一个外函数中,
  2. 内函数引用了外部函数的变量
  3. 外部函数的返回值为内函数本身,则这个内函数成为闭包函数
  • 下面的例子中,test1就是一个闭包函数
def test(a):
    name = "test22"
    def test1(b):
        name = "test44"
     return test1   
闭包函数的作用

上下文管理器

基本语法

with 表达式 as name:
	代码块
  1. 上下文表达式:with open('test.txt') as file
  2. 上下文管理器:open('test.txt')

如何写一个上下文管理器

  1. 只需要在类中实现上下文管理协议,即定义__enter____exit__方法即可,这个类的实例就是上下文管理器

  2. 在执行方法时,会首先调用enter,随后调用exit方法,类似于AOP

  3. enter方法必须返回对象本身,exit方法参数必须有四个

class Person:

    def __enter__(self):
        print('方法执行前。。。。')
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('方法执行后。。。。')

    def test(self, a, b):
        print(a + b)
        return a + b  

    def test1(self, b, d):
        print(b * d)
        return b * d      

with Person() as person:
    person.test(3,4)
    person.test1(3,4)

person.test(3, 6)

类和对象

基本定义

class className(Object):
	name = ""
	def __init__(self, name):
		self.name = name
    def method1(self, name):
    	方法体
    def method2:
    	方法体
  1. (object)用来指定父类,默认所有的类父类都是object,也可以不用写,即class className:class className():

  2. __init__为构造函数

  3. 实例化方式:

    • 根据参数位置构造:object = className("knxhd")
    • 根据参数名称构造:object = className(name="sf")
  4. 调用函数方式:

  5. object.method1("qwqewqw")

  6. object.method(object, "eferfge")

  7. 调用属性方式:object.name

静态方法和实例方法

  1. 静态方法:使用staticmethod修饰的方法
  2. 实例方法:使用classmethod修饰的方法
  3. 普通方法:没有修饰器的方法
class Person:
    name = ""

    def __init__(self, name):
        self.name = name
    
    @staticmethod
    def equal(self, name):
        return self.name == name

    @classmethod
    def toString(cls):
        return cls   

    def run(self):
        print(f"{self.name}启动成功")
  1. 静态方法中的参数selfname在调用时,都需要传入,否则会出现异常。定义时,可以不用写self。
  2. 实例方法参数中的cls表示类本身,类似与Class<?>,调用时不需要传入
  3. 普通方法第一个参数self表示对象本身,调用时不需要传入

:star: 普通函数(未定义在类中)和静态方法,实例方法类型都是函数(function)

:star: 类方法的类型是方法(method)

:star2: 可通过type()方法进行验证

继承父类

  • 定义父类,例如动物类Animal
class Animal():
   
   name = "父类属性"
   
   def __init__(self, type):
       self.type = type
       
   def method1(self):
       print("父类方法1")
   
   def method2(self):
       print("父类方法2")
  • 定义子类方法继承父类
class Dog(Animal):

  def __init__(self, type):
       super().__init__(type)
       
   def method(self):
       print("子类方法")
  • 使用父类的方法和属性
dog = Dog("狗")

#调用父类方法
dog.method1()

#调用父类属性
print(dog.type)
print(dog.name)

引入模块

  • 在Python中,使用import或者from ... import来导入相应的模块
  • 将整个模块(module)导入,格式为 import somemodule
  • 从某个模块引入某个函数:from somemodule import somefunction
  • 从某个模块引入多个函数:from somemodule from somefunction, somefunctoin2
  • 从某个模块引入全部函数:from somemodule import \*

IO操作

文件操作

open函数

  • 使用open(str, option)可以对文件进行操作,其中,str表示操作的文件路径,option表示操作文件的权限,其值有以下几种

  • r:只读,此时不能够写入文件

  • w:只写,此时不能写入和执行

  • x:可执行

  • r+:既可读也可写入

  • a:可写入,同时非追加内容到后面,w会覆盖原来的文件内容,a是如果文件存在,则内容追加到后面

  • b:二进制文件,此模式,不能直接使用write(str)写入字符串,需要转成二进制字节

    open("test.txt", 'rb')
    
  • 官方推荐写法

  • 在使用open时,一般需要捕获异常,同时将close()放到finally中,防止资源不能释放,出现内存问题

try:
    file = open("test.txt", "wb")
    print(file.readable())
    print(file.writable())
    file.write("====")
except Exception as e:
    raise RuntimeError("文件操作异常")
finally:
    print("关闭===")
    file.close()
  • 官方推荐使用with来定义文件,这样可以自动释放资源
with open('test.txt', 'b+') as file:
    print(file.readable())
    print(file.writable())

Python3标准库

文本处理

  • string:类是 Python 编程者最常用的文本处理工具。
  • textwrap:模块就内置一些工具来格式化段落中的文本,比如设置文本每行输出行宽度,添加缩进,以及插入换行来保证每行的一致性等。
  • re:提供了一个完整高效的 C 语言形式内置的正则表达式库。正则表达式很适合在大量数据中查找子串,将一个字符串与另一个更复杂的固定字符串进行比较,以及进行温和句法分析。
  • difflib:则根据增加、删除、更改的部分来计算文本字符序列之间的实质差别。difflib 中的比较函数能为使用者提供更加详细的关于两组输入中的不同点所在、文档随时间而变化等方面的反馈。

string

函数

capwords(首字母大写)
  • 示例:
s = 'The quick brown fox jumped over the lazy dog.'

print(s)
print(string.capwords(s))

"""
 输出结果:
 The quick brown fox jumped over the lazy dog.
 The Quick Brown Fox Jumped Over The Lazy Dog.
"""

正则表达式

  • 模块:re

正则表达式语法

元字符
字符含义
^以字符开始
$以字符结束
*零个或多个
+至少一个字符
?0个或1个
{n,m}1、{n}:匹配n个 2、{n,} 至少n个 3、{n,m} n~m个
[]字符合集
()匹配 pattern 并获取这一匹配
\转义字符
分组捕获(?ppattern),可通过group(name)进行捕获
转义字符
代码含义
\d一个数字
\D一个非数字
\s空白字符 (制表符,空格,换行符等等。)
\S非空白字符
\w由字母和数字组成的
\W非字母和数字组成的

search(pattern, text)

  • search函数表示在文本中匹配正则表达式,如果找到对应的词,则返回一个match对象,否则返回None
  • search为模糊匹配,判断文本是否包含正则表达式表示的字符。和match相对应,match用于匹配以正则表示字符开始
示例1
import re

pattern = "([0-9])(?P<test>[0-9]*)"
print("输入文本:", end = "")
text = input("")

match = re.search(pattern, text)

if match != None:
    print("输入正确")
    print(f"start:{match.start()}")
    print(f"end:{match.end()}")
    print(f"group:{match.group()}")
    print(f"groups:{match.groups()}")
    print(f"group(1):{match.group(1)}")
    print(f"groupdict:{match.groupdict()}")
    print(f"groupByname:{match.groupdict().get('test')}")
    print(f"regs:{match.span()}")
else:
    print("输入不正确")

"""
	输入:2322weew
	输出:
		输入文本:2322weew
        输入正确
        start:0
        end:4
        group:2322
        groups:('2', '322')
        group(1):2
        groupdict:{'test': '322'}
        groupByname:322
        regs:(0, 4)
"""   
match内置函数
  • 当通过search()获得match对象后,可以调用内部方法获得一些数据
  1. start():匹配到文本的开始索引
  2. end:匹配到文本的结束索引
  3. group:获得正则表达式捕获分组
pattern = "^([0-9])([0-9]*)"
print("输入文本:", end = "")
text = input("")

match = re.search(pattern, text)

if match != None:
   print("输入正确")
   print(f"start:{match.start()}")
   print(f"end:{match.end()}")
   print(f"group:{match.group()}")
   print(f"group:{match.group(1)}")
else:
   print("输入不正确")
  1. groups()获得捕获结果,类型为元组
  2. groupdict():获得捕获结果,类型为字典,数据为分组添加别名的哪些捕获组
pattern = "^([0-9])(?P<test>[0-9]*)"
match = re.search(pattern, "23423wfewr")
print(f"groupdict:{match.groupdict()}")
print(f"groupByname:{match.groupdict().get('test')}")

"""
输出结果:
groupdict:{'test': '3423'}
groupByname:3423
"""

compile

  • 将普通文本转为正则编译器,类似于java中的Pattern pattern = Pattern.compile(".*");
  • 其内置的方法和re相同
"""
    预编译字符串
"""
import re

# pattern = "^[0-9]?P<test>[0-9]*"
pattern = "^[0-9][0-9]*"
print("输入文本:", end = "")
text = input("")

regex = re.compile(pattern)

match = regex.search(text)

fullmatch

  • 返回结果依然为match对象,如果未匹配到,则返回None
  • 不同的是fullmatch为全匹配,也就是精确匹配
import re

# pattern = "^[0-9]?P<test>[0-9]*"
pattern = "^[0-9][0-9]*"
print("输入文本:", end = "")
text = input("")


regex = re.compile(pattern)
fullmatch = regex.fullmatch(text)
print(f"fullmatch(精确匹配):{fullmatch}")
print(f"fullmatch(精确匹配):{re.fullmatch(pattern, text)}")

match

  • 返回结果依然为match对象,如果未匹配到,则返回None
  • fullmatch相对应,即模糊匹配
  • search不同的是,search判断文本是否包含正则表达式表示的字符,match用于匹配以正则表示字符开始
pattern = "^[0-9][0-9]*"
print("输入文本:", end = "")
text = input("")


regex = re.compile(pattern)
match = regex.match(text)

print(f"match(模糊匹配):{match}")
print(f"match(模糊匹配):{re.match(pattern, text)}")

findall

  • 和search类似,search返回结果为match对象,仅仅会匹配出第一个满足条件的
  • findall返回满足条件的list集合
示例
import re

pattern = "(?P<test>[0-9]+)"
print("输入文本:", end = "")
text = input("")

print(re.findall(pattern, text))
print(type(re.findall(pattern, text)))

"""
输入文本:e23efe22bb3434
['23', '22', '3434']
<class 'list'>
"""

finditer

  • 和findall类似,不同的是finditer会返回一个包含match对象的迭代器
  • 通过for循环可以遍历匹配结果
示例
import re

pattern = "(?P<test>[0-9]+)"
print("输入文本:", end = "")
text = input("")

itera = re.finditer(pattern, text)
print(type(itera))

for item in itera:
    print(item.group())
    print(item)

"""
输入文本:ferfer43freer34233
<class 'callable_iterator'>
43
<re.Match object; span=(6, 8), match='43'>
34233
<re.Match object; span=(13, 18), match='34233'>
"""    

匹配选项

不区分大小写
  • IGNORECASE 会使该模式下的文字字符和字符范围既能匹配大写字符又能匹配小写字符

  • compile中同样适用

import re

pattern = "[a-z]+"

print("输入文本:")
text = input("")

print(f"区分大小写:{re.search(pattern, text)}")
print(f"不区分大小写:{re.search(pattern, text, re.IGNORECASE)}")

"""
输入文本:
232WRE  
区分大小写:None
不区分大小写:<re.Match object; span=(3, 6), match='WRE'>
"""
多行输入
  • MULTILINE 标志控制模式匹配代码如何处理包含换行符文本的锚定指令
pattern = "(^[a-z]+)|([a-z]+$)"
text = """
    aaaa
    1111bbbb

"""
print(f"区分多行写:{re.search(pattern, text)}")
print(f"不区分多行写:{re.search(pattern, text, re.MULTILINE)}")

"""
区分多行写:None
不区分多行写:<re.Match object; span=(10, 14), match='aaaa'>
"""
  • DOTALL
  • 在正则中.表示任意字符,而DOTALL可以使.可以匹配换行符
import re

pattern = "(^[a-z]+)|([a-z]+$)"
text = """
aaaa
1111bbbb
"""
print(f"区分多行写:{re.search(pattern, text)}")
print(f"不区分多行写:{re.search(pattern, text, re.MULTILINE)}")

print(f"DOTALL_不区分多行写:{re.search(pattern, text, re.DOTALL)}")

"""
区分多行写:<re.Match object; span=(10, 14), match='bbbb'>
不区分多行写:<re.Match object; span=(1, 5), match='aaaa'>
DOTALL不区分多行写:<re.Match object; span=(10, 14), match='bbbb'>
"""

日期和时间

  • Python 并没有像对 int, float,和 str 一样为日期与时间提供原生类型,但仍然有三个模块可以对日期和时间的几种表现形式进行处理。
  • time:模块暴露了底层 C 语言库中的时间相关函数。它包含了检索时钟时间(clock time)和处理器运行时间的函数,以及基本的解析工具和字符串格式化工具。
  • datetime:模块为日期,时间,以及两者的结合提供了一个更高级的接口。datetime 中的类支持四则运算,大小比较,还有时区配置
  • calendar:模块创建了数周,数月,数年的的格式化表示。它也可以用来计算周期性的事件,计算给定日期是一周中的第几天,以及计算其他基于日历的值

time

实战

  • 在进行网络爬虫或其他数据分析时,需要安装依赖,在切换到不同设备时,需要重新下载依赖,比较麻烦

  • 可以通过pip生成项目所需依赖的txt文件,统一进行安装

  • pip freeze>requrements.txt生成依赖到文件中

  • pip install -r requrements.txt批量更新依赖

  • pip镜像

网络爬虫

-爬虫可以简单分为几步:抓取页面、分析页面和存储数据。

在抓取页面的过程中,我们需要模拟浏览器向服务器发出请求,所以需要用到一些 Python 库来实现 HTTP 请求操作。在本书中,我们用到的第三方库有 requests、Selenium 和 aiohttp 等。

在本节中,我们介绍一下这些请求库的安装方法。

准备工作

请求库安装

  1. requests:http请求库,安装方式:pip3 install requests

  2. Selenium:自动化测试工具,可以模拟浏览器执行点击、下拉等操作。安装方式;pip3 install selenium

  3. aiohttp:异步http请求,requests是同步操作。安装方式:pip install aiohttp

  4. ChromeDriver:谷歌浏览器驱动,需要此工具驱动浏览器进行一些操作,例如点击等。需要安装了谷歌浏览器

  5. GeckoDriver:火狐浏览器驱动,和ChromeDriver类似,需要安装了火狐浏览器

  6. PhantomJS

  • PhantomJS 是一个无界面的、可脚本编程的 WebKit 浏览器引擎,它原生支持多种 Web 标准:DOM 操作、CSS 选择器、JSON、Canvas 以及 SVG。
  • Selenium 支持 PhantomJS,这样在运行的时候就不会再弹出一个浏览器了。而且 PhantomJS 的运行效率也很高,还支持各种参数配置
ChromeDriver

20220427093344184

GeckoDriver
PhantomJS

解析库安装

  1. lxml:lxml是Python的一个解析库,支持HTML和XML的解析.安装方式:pip3 install lxml
Beautiful Soup
  • Beautiful Soup 是 Python 的一个 HTML 或 XML 的解析库,我们可以用它来方便地从网页中提取数据。它拥有强大的 API 和多样的解析方式
from bs4 import BeautifulSoup  
soup = BeautifulSoup('<p>Hello</p>', 'lxml')  
print(soup.p.string)
pyquery
  • pyquery 同样是一个强大的网页解析工具,它提供了和 jQuery 类似的语法来解析 HTML 文档,支持 CSS 选择器。
python3
>>> import pyquery
tesserocr
  • 在爬虫过程中,难免会遇到各种各样的验证码,而大多数验证码还是图形验证码,这时候我们可以直接用 OCR 来识别

  • tesserocr 是 Python 的一个 OCR 识别库,但其实是对 tesseract 做的一层 Python API 封装,所以它的核心是 tesseract。因此,在安装 tesserocr 之前,我们需要先安装 tesseract

  • 安装

pip3 install tesserocr pillow
tesseract
  • 下载地址中不带dev的是稳定版本,可以选择自行下载

  • MAC下安装方式:

brew install imagemagick   
brew install tesseract --all-languages
  • 配置安装目录到环境变量path中
  • 新建环境变量TESSDATA_PREFIX,目录为tesseract目录下的\tessdata
  • 可以通过命令行验证是否安装成功, image.png为带文件的图片,看是否可以识别文字
tesseract image.png result -l eng
tesserocr
  • tesserocr可以通过命令行安装 pip install tesserocr pillow,此命令是同时安装pillow和tesserocr

  • 如果命令行安装出现异常,则可以通过下载安装包手动安装

  • 运行下面的代码验证是否安装成功
import tesserocr  
from PIL import Image  
image = Image.open('testFile/image.png')  
print(tesserocr.image_to_text(image))

数据库驱动

数据库驱动操作对应的数据库

  1. pymysql pip install pymysql
  2. pymongo pip install pymongo
  3. redis pip install redis

web库

  1. Flask
  2. Tornado