正则表达式与文件操作

正则表达式

正则表达式是一种被用于从文本中检索符合某些特定模式的文本。

基本匹配

"foo" 匹配所有包含foo的文本

元字符

元字符 描述
. 匹配除换行符以外的任意字符。(长度为1)
[ ] 字符类,匹配方括号中包含的任意字符。
否定字符类。匹配方括号中不包含的任意字符
* 匹配前面的子表达式零次或多次
+ 匹配前面的子表达式一次或多次
? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。
{n,m} 花括号,匹配前面字符至少 n 次,但是不超过 m 次。
(xyz) 字符组,按照确切的顺序匹配字符xyz。 把括号内的内容提取出来
\ 分支结构,匹配符号之前的字符或后面的字符。
\ 转义符,它可以还原元字符原来的含义,允许你匹配保留字符 `[ ] ( ) { } . * + ? ^ $ \ `
^ 匹配行的开始
$ 匹配行的结束
\b 结束占位符,类似于$
.fu # 代表任意字符后面跟着fu,这里的字符必须有一个。 所以匹配fu会出错
#    字符集
[Tt]fu # 字符集 大写或者小写t,后面跟着fu
ar[.] # 特殊的表示小写字母 a,后面跟着一个字母 r,再后面跟着一个英文句号 . 字符。
[a-z] # a-z的小写字母
[a-z0-9_-] # a-z的小写字母或者0-9的数字或者_或者-
[^c]ar  # 除了字母 c 以外的任意字符,后面跟着字符 a, 再后面跟着一个字母 r
# 重复

#  * 零次或者多次
#  + 一次或者多次
# ? 零次或一次
[a-z]*  # 一行中可以包含任意数量的小写字母。
.* # 任意字符串
\s* # 匹配空字符
c.+t # 一个小写字母 c,后跟任意数量的字符,后跟小写字母 t。
[T]?he # 可选的大写字母 T,后面跟小写字母 h,后跟小写字母 e

[0-9]{2,3}  # 匹配至少2位数字但不超过3位(0到9范围内的字符)。其实就是长度
[0-9]{2} # 匹配正好为2位数的数字。
[0-9]{2,} # 匹配2个或更多个数字
[a-f]{4} # 匹配一个字符,这个字符需要有连续4个字符,字符内容是a-f中的字母
(c|g|p)ar # 小写字母 c、g 或 p 后面跟字母 a,后跟字母 r。
(f|c|m)at\.? # 小写字母 f、c 或者 m 后跟小写字母 a,后跟小写字母 t,后跟可选的 . 字符。
^(T|t)he # 大写字母 T 或小写字母 t 是输入字符串的起始符号,后面跟着小写字母 h,后跟小写字母 e。
ick$ 匹配以ick结尾的字符
fu\b 匹配以fu结尾的字符
(at\.)$ # 小写字母 a,后跟小写字母 t,后跟一个 . 字符,且这个匹配器必须是字符串的结尾。
(.*?)匹配任意字符0次或多次,模式为非贪婪模式
:(.*?)你 #小括号提取内容,直接将会出来`:我的你`,如果只要匹配`我的`,那么需要加上括号

解释.*.*?的区别

.代表除换行符外的字符

*代表匹配它前面的字符0次或者任意多次

.*代码匹配一串任意长度的字符任意次,贪婪模式,获取最长能满足条件的字符串

?限制返回,返回最短字符串,而不是整个字符

.*?匹配能满足要求的最短字符,非贪婪模式,获取最短能满足条件的字符串

{} () []

  • {2,3} 花括号 频次
  • (.*?) 选中 匹配 括号不包括控制两端
  • [] 范围,匹配到的东西必须出现在这个中括号里面

简写字符集

简写 描述
. 匹配除换行符以外的任意字符
\w 匹配所有字母和数字的字符,不包括空格和双引号: [a-zA-Z0-9_]
\W 匹配非字母和数字的字符: [^\w]
\d(digital) 匹配数字: [0-9]
\D 匹配非数字: [^\d]
\s 匹配空格符: [\t\n\f\r\p{Z}]
\S 匹配非空格符: [^\s]

引用

这个\1  \2......  都要和正则表达式集合()一起使用简单的说就是\1表示重复正则第一个圆括号内匹配到的内容\2表示重复正则第二个圆括号内匹配到的内容
(...).*\1 # 三个字的任意字符,后面再加上某个字符(或者没有),再将这三个字符重复一遍

正则模块

re

  • findall 以列表的形式返回所有满足要求的字符串,所以要再读取,要加上引号
  • search 返回第一个满足要求的字符串

findall

findall(pattern, str, flags)
# pattern 正则
# str 原来的字符串
# flags 特殊功能的标识符:忽略大小写、忽略换行符等 
    # re.S 忽略换行符
# return 返回一个匹配的列表,如果没有匹配到,就返回空列表
import re

content_text = '我的微博密码是:12345678,银行卡密码是:98888,github密码是:aasdad123,'
password_list = re.findall(':(.*?),', content_text)
print("找到内容,返回{}".format(password_list))

content_text2 = '我的微博账户是:1232,密码是:12345678,银行卡账户是:123213,密码是:98888,github账户是:git,密码是:aasdad123,记住他们'
password_list2 = re.findall('账户是:(.*?),密码是:(.*?),', content_text2)
print("找到内容,返回{}".format(password_list2))

content_text3 = '''
    我是kingname,我的微博密码是:123
    456,
'''
password_list3 = re.findall('密码是:(.*?),',content_text3, re.S)
print('密码是{}'.format(password_list3))

search只会返回第一个满足要求的字符串,一旦找到符合要求的内容,它会自动停止查找。

返回结果:如果匹配成功,返回正则表达式对象,否则的话,返回None,获取匹配结果,需要使用group, group的参数最大不超过正则表达式里面括号的个数,参数为1表示读取第一个括号的你日工,参数为2表示读取第二个括号的内容

re.search(pattern, string, flags=0)
import re
# search的使用
account_content = '微博账户是: vine, 密码是: 123456, 微信密码是: abs123, qq密码是: 485uiu,'
account_password = re.search('账户是: (.*?), 密码是: (.*?),', account_content)
print("账户:{}".format(account_password.group(1)))
print("密码:{}".format(account_password.group(2)))

技巧

  1. 使用findall,不使用compile
  2. 先抓大再抓小
  3. 括号内和括号外

搜索密码

# 今天是一个好天气 password:123456:password.我在读书,书的第二页写着password:qwer1234:password啊.
import re
with open('password.txt', encoding='utf-8') as f:
    text_content = f.read()
    password = re.findall('password:(.*?):password', text_content)
    print(password)

抓大放小

import re
big_small_text = '''
有效的用户:
姓名:张三
姓名:李四
姓名:王五
无效的用户:
姓名:不知名的小虾米
姓名:隐身的源大侠
'''
user_list = re.findall('有效的用户:(.*?)无效的用户', big_small_text, re.S)
useful_user_list = re.findall('姓名:(.*?)\n', user_list[0])
print(useful_user_list)

文件操作

创建文件夹

  • 参数1:创建文件夹的名称
  • 参数2 :如果已存在文件夹,是否保留原来文件夹并不再重新创建
os.makedirs('动物农场', exist_ok=True)

创建文件

  • 参数1:要创建文件的文件夹
  • 参数2:文件名称
file_path = os.path.join('动物农场', chapter + '.txt')
with open(file_path, 'w', encoding='utf-8') as f:
    f.write(article)

打开文件

# 方法一:需要手动关闭文件
f = open('文件路径','文件操作方式',encoding='utf-8');
# 对文件进行操作
f.close()
# 方法二:代码缩进自动关闭文件
with open('文件路径', '文件操作方式', encoding='utf-8') as f:
    #对文件进行操作

读取文件

  • r ==> read
  • 绝对路径/相对路径:linux和Mac OS不能直接使用~表示home目录
  • encoding:utf-8 打开文件时将文件转换为utf-8的编码格式
  • f.readlines:读取所有行,并以列表的形式返回结果
  • f.read() 直接将文件中的所有内容用一个字符串返回
# 读取文本文件

# 按行读取
# 结果 ['1111111111111111111111\n', '2222222222222222222222\n', '333333333333333333333']
with open('text.txt', encoding='utf-8') as f:
    content_list1 = f.readlines()
    print(content_list1)

# 全部文件读取
# 结果 
# 1111111111111111111111
# 2222222222222222222222
# 333333333333333333333
with open('text.txt', encoding='utf-8') as f:
    content_list2 = f.read()
    print(content_list2)

写入文件

  • w ==> write 会覆盖原来的文件
  • a ==> append 会将内容加到原来文件的结尾
with open('text.txt', 'w', encoding='utf-8') as f:
    通过f来写文件
# 写入文本
with open('text.txt', 'w', encoding='utf-8') as f:
    f.write("======写入文本=======\n")
    f.write("一大段文字")
    f.write("\n===========将列表中的所有字符串写入文本========\n")
    f.writelines(["列表元素1", "列表元素2"])



======写入文本=======
一大段文字
===========将列表中的所有字符串写入文本========
列表元素1列表元素2

读写csv文件

读入

import csv
# 返回的是row或者orderedDict(有序字典)
with open('test.csv', encoding='gbk') as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row)

写入

writer = csv.DictWriter(文件, fieldnames); 
# fieldnames的值为字典的key列表
writer.writeheader() #写入csv文件的列名
writer.writerow(单个字典) 
writer.writerows(包含字典的列表)
import csv

data = {'访问': '未知', '名称': '某种电脑'}
with open('test.csv', 'a', encoding='gbk') as f:
    writer = csv.DictWriter(f, fieldnames=['序号', '访问', '名称'])
    writer.writerow(data)

实例

采集贴吧信息