豪翔天下

Change My World by Program

0%

Python字符串与时间处理

常用操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# 字符判断
string.isalpha() # 是否为字母
string.isdigit() # 是否为数字
string.isalnum() # 是否为数字或字幕
string.islower() # 是否都是小写
string.isupper() # 是否都是大写
string.istitle() # 是否都首字母大写
string.isspace() # 是否都是空白字符

# 格式化字符串
'abcdef %s' % (123) # 特别适合长字符串不用加号来拼接字符串的情况
"my name is {name}".format(name=name) # 这种方式好处是可以直接定义名字
"my name is {} at {}".format(name, address) # 这种方式可以在少数变量的情况下偷一下懒
"{1} {0} {1}".format("hello", "world") # 可以指定位置
f'my name is {变量名}' # Python3.6里面新增的特性,可用这种方式直接格式化字符串
f'{name=}' # python3.8开始直接这样可以输出name=value形式的字符串
f'{{}}' # 直接插入大括号
my_dict = {'name': '...', 'addr': '...'}
'my name is {name} at {}'.format(**my_dict) # 直接解析字典的参数
my_list = {'name', 'addr'}
'my name is {0[0]} at {0[1]}'.format(my_list) # 直接解析列表的参数
''.join(['a','b']) # 合并字符串列表并增加分隔符,需要注意的是列表中必须为字符串,如果是数字需要强制转换一下

# 格式化数字
'{:.2f}'.format(3.1415926) # 3.14, 保留两位小数

# 指定列宽格式化字符串
import textwrap
print(textwrap,fill(s, 70)) # 将s字符串已70列显示,多的换行
os.get_terminal_size().columns # 可以使用这个方法获得终端的大小和尺寸

# 字符串填充,数字前补零
a = 'abc'
print(a.zfill(5)) # 输出'00abc'

# 去掉空格
s.strip() # 去掉两端空白
s.lstrip() # 去掉左边空白,加参数可以
s.rstrip() # 去掉右边空白
s.replace(' ', '') # 去掉所有空白
s.removeprefix('.png') # py3.9,删除后缀
s.removesuffix('abc') # py3.9,删除前缀

# 大小写转换
s.upper() # 全部转为大写
s.lower() # 全部转为小写

# json格式去掉冒号后的空格
json.dumps(string, separators=(',', ':')) # 默认的分隔符是(', ', ': ')
# json格式输出中文而不是unicode字符串
json.dumps(string, ensure_ascii=False)

# url编码与解码
from urllib import parse
parse.unquote(url) # url解码
result = parse.urlparse(url) # url解析
query_dict = parse.parse_qs(request.query) # 获取查询参数
query_dict.get('field', []) # 获取指定参数

# 进制转换
binascii.b2a_hex(string.encode('utf-8')) # 字符串转16进制

''.join(random.sample(string.ascii_letters + string.digits, 10)) # 生成随机字符串

查找与替换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# startswith
str.startswith(str, beg=0, end=len(string))
str.endswith(str)

# 统计子字符串出现次数
str.count('sub_str')

# 字符串替换
import re
text = 'Today is 03/16/2023'
pat = re.compile(r'(\d+)/(\d+)/(\d+)')
pat.sub(r'\3-\1-\2', text)
'Today is 2016-11-27'

>>> text = 'Today is 03/16/2023, tomorrow is 03/17/2023'
>>> re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text)
'Today is 2023-03-16, tomorrow is 2023-03-17'

# 带命名组的替换
re.sub(r'<a.*?>(.*?)</a>','\g<1>', text) # 替换a标签,但保留a标签里面的内容,需要注意的是.*表示最长匹配,而.*?表示最短匹配。添加参数flag=re.IGNORECASE表示不区分大小写

# 对替换做特殊处理
print(re.sub('(?P<value>\d+)', lambda matched: str(int(matched.group('value')) * 2), s))

# 使用正则方式查找
import re
url = 'http://haofly.net/note.html'
match = re.search('(.*)/(.*?).html', a)
match = re.search('(.*)/(.*?).html', a, re.IGNORECASE) # 不区分大小写的正则匹配
print(match.group(1), match.group(2))

# 基本查找,返回第一个出现该字符串的位置
text.find(',')

# 查找某字符串出现的所有位置的一个列表
[m.start() for m in re.finditer(',', text)] # 输出[4, 11]

# 忽略大小写的查找
re.findall('python', 'text, flags=re.IGNORECASE)

# 查找所有匹配的
matches = re.findall('pattern', string) # 返回所有匹配的列表

# 最短匹配
str_pat = re.compile(r'\\"(.*?)\\"')
str_pat.findall(text2) # 输出['no.', 'yes.']

# 查找时中文编码问题
re.search('中文(.*?)呵呵'.decode('utf8'), string)

# 字符串分割-正则方式
line = 'asdf fjdk; afed, fjek, asdf, foo'
import re
re.split(r'[;,\\s]\\s_', line) # ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
re.split(r'(;|,|\\s)\\s_', line) # 这样连分隔符都能分割出来
re.split('(==|>=|<=|>|<)', 'requests>1.2.3') # 多个字符的解析

时间处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# 简单的获取时间:
import datetime
a = str(datetime.date.today())
print(a) # 格式为2015-07-17
a = time.strftime('%H:%M:%S') # 格式为11:20:00
time.strftime('%Y-%m-%d %H:%M:%S')

# 获取当前时间时间戳
time.time()

# 字符串转时间:
time_str='Tue, 11 Nov 2014 06:37:20 +0000'
date = datetime.datetime.strptime(time_str, '\%a, \%d \%b \%Y \%H:\%M:\%S \%z')
print(date) # 输出'2014-11-11 06:37:20+00:00'
print(date.timestamp()) # 输出时间戳'1415687840.0'
# 或者
date = datetime.datetime(2006, 12, 12, 12, 12, 12)

# 获取当天开始和结束的时间(即00:00:00到23:59:59)
today = datetime.date.today()
datetime.datetime.combine(today, datetime.time.min)
# 得到datetime.datetime(2015, 7, 24, 0, 0)
datetime.datetime.combine(today, datetime.time.max)
# 得到datetime.datetime(2015, 7, 24, 23, 59, 59, 999999)

# 时间加一天,加一分钟,昨天,明天,前面几天,后面几天
now = datetime.datetime.now()
date = now + datetime.timedelta(days = 1)
date = now + datetime.timedelta(seconds = 3)

# 关于时间占位符总结:
%d:日
%b:简写的月份,如Oct
%Y:年份
%H:小时
%m:月
%M:分钟
%S:秒
%z:与时区相关,在标准时间上加时间,例如'+00:00'

# 各种格式举例
time.strftime('%Y-%m-%dT%H:%M:%S%z') # 2015-11-11T02:49:03+00:00

# 转换时间为UTC/GMT时间
time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(time.mktime(time.strptime("2008-09-17 14:04:00", "%Y-%m-%d %H:%M:%S"))))

# 时间戳的转换:
ltime=time.localtime(1395025933)
timeStr=time.strftime("\%Y-\%m-\%d \%H:\%M:\%S", ltime)

string = '2015年09月18日 00:01:00'
date = time.strptime(string, '\%Y年\%m月\%d日 \%H:\%M:\%S')
b = time.mktime(date) # 获取时间戳

# datetime转时间戳
time.mktime(the_date.timetuple())

# 时间戳转datetime
datetime.datetime.fromtimestamp(1234567890)

# 获取本月有多少天,以及最后一天的计算方法
import calendar
today = datetime.date.today()
_, last_day_num = calendar.monthrange(today.year, today.month)
last_day = datetime.date(today.year, today.month, last_day_num)

# 计算间隔时间
begin = datetime.datetime(2015, 3, 14, 23, 59, 59)
today = datetime.datetime.today()
interval = today - begin
interval.seconds() # 时间差多少秒
interval.days # 相差多少天,对应的.seconds表示相差多少秒,小时等同理

编码问题

  • 2中打印str显示前面加了个u且中文类似\u8be5\u9879:这是十六进制的Unicode编码,使用string.encode('utf-8')进行转换

  • 2中类似\uiahd\u9483这样的字符串:需要注意的是,该字符串本来就是这样,而不是编码成这样的,这时候需要反编码:string.decode('unicode_escape'))

  • 2中无法输出中文: 无论是str还是unicode还是encode('utf-8')都无法输出中文,可以试试在print的时候不带括号: print a,但是print一个对象依然不行,可以单独打印某个字段

  • 无法解析\u2c这样的unicode字符,出现错误UnicodeDecodeError: 'unicodeescape' codec can't decode bytes in position 0-3:truncated \uXXXX escape: 原因是unicode默认是\uxxxx这样的形式来解析字符串的,但是如果出现\u2c这种,是解析不了的,应该写成\u002c这种形式,前面需要补全

  • UnicodeDecodeError: ‘ascii’ codec can’t decode byte: 可以试试unicode(string, 'utf-8)

  • url编码 Python3中,url编码放在了url lib.parse中了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # python3
    from urllib import parse
    parse.quote(str) # urlencode
    parse.quote_plus(str)
    parse.unquote(str) # urldecode
    parse.encode() # 把字典转换为query的方式

    # python2
    urllib.urlencode(dict)
    urllib.quote(str)
    urllib.unquote(str) # urldecode
  • bytes to string/字节转字符串

    1
    b"abcde".decode('utf-8')
  • string to bytes/字符串转字节

    1
    str.encode("abcfc")
  • 将字符串输出为16进制字节:

    1
    2
    3
    4
    ":".join("\{:02x\}".format(ord(x) for x in 字符串))
    # 或
    ":".join("\{0:x\}".format(ord(x) for x in 字符串))
    # 输出类似于: 12:45:45
  • 16进制转换为utf-8 :类似 \xe5\x94\xae\这种,使用如下方式进行转换

    1
    2
    3
    4
    5
    6
    7
    # 方法一
    unicode(string, 'utf-8')

    # 方法二
    a = u'xb3\xe5'
    b = array('u', a).tostring()[::2].decode('gbk')
    print(b)
  • base64编码和解码

    1
    2
    3
    import base64
    a = base64.b64encode(s)
    b = base64.b64decode(a)
  • gb2312字符串转换为utf-8

    1
    data.encode('latin1').decode('gb2312')
  • 大端/小端

    Python使用struct.pack和struct.unpack来将数据封装成大端/小端的字节流,例如struct.pack('>h',14)表示将14封装成大端模式

  • 查看字符编码

    1
    2
    import chardet
    chardet.detect(string)

TroubleShooting

  • “TypeError: Unicode-objects must be encoded before hashing”

    原因是在3.x中,md5方法仅接受unicode编码过后的字符串:

    1
    hashlib.md5(string.encode('utf-8')).hexdigest()
坚持原创技术分享,谢谢支持

欢迎关注我的其它发布渠道