json、网络与正则表达等 python复习笔记

Python JSON 数据解析

JSON(JavaScript Object Notation)是一种轻量级数据交换格式,它易于阅读和编写,同时也易于机器解析和生成。Python提供了内置的JSON模块,用于处理JSON数据。

1. 导入模块

import json

2. 序列化

import json
data = {
    
    
    "name": "John",
    "age": 30,
    "city": "New York"
}

json_str = json.dumps(data)  # json.dumps() 是 Python 的 json 模块中的一个函数,它的作用是将 Python 对象转换为 JSON 格式的字符串。
print(json_str)

3. 反序列化

json_str = '{"name": "John", "age": 30, "city": "New York"}'

data = json.loads(json_str) # json.loads() 是 Python json 模块中的一个函数,它的作用是将 JSON 格式的字符串转换为 Python 对象。
print(data)

4. 对象存文件

data = {
    
    
    "name": "John",
    "age": 30,
    "city": "New York"
}

with open('data.json', 'w') as json_file:
    json.dump(data, json_file)

5. 从文件加载

with open('data.json', 'r') as json_file:
    data = json.load(json_file)
    print(data)

6. 嵌套JSON数据

如果JSON数据包含嵌套结构,您可以使用递归来访

问和修改其中的值。

json_data = {
    
    
    "name": "Alice",
    "info": {
    
    
        "age": 25,
        "location": "Paris"
    }
}

# 获取嵌套的值
age = json_data["info"]["age"]

# 修改嵌套的值
json_data["info"]["location"] = "New York"

# 将更改后的数据转换为JSON字符串
new_json_str = json.dumps(json_data)

7. JSON中列表

JSON可以包含列表,可以使用索引来访问列表元素。

json_data = {
    
    
    "fruits": ["apple", "banana", "cherry"]
}

# 获取列表中的第一个水果
first_fruit = json_data["fruits"][0]

# 添加一个新水果到列表
json_data["fruits"].append("orange")

8. JSON中空值

JSON允许表示空值(null),在Python中,它通常转换为None

json_data = {
    
    
    "value": None
}

字典和JSON格式不同之处

  1. 数据类型限制
    • JSON:支持的数据类型包括对象(类似于字典)、数组(类似于列表)、字符串、数字、布尔值和 null。JSON 不支持 Python 特有的数据类型如 tuplesetbytes 等。
    • Python 字典:可以包含多种 Python 特有的数据类型,比如 tuplesetbytes 等。
  2. 格式要求
    • JSON:数据必须以字符串的形式表示,键必须是双引号括起来的字符串,值可以是字符串、数字、布尔值、数组、对象或 null
    • Python 字典:键可以是任意不可变的类型(如字符串、数字、元组),值可以是任意类型。键通常用单引号或双引号括起来,但 Python 允许在字典中使用不加引号的键。

Python正则表达式

正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。re模块使 Python 语言拥有全部的正则表达式功能。正则表达式在网络爬虫、数据分析中有着广泛使用,掌握正则表达式能够达到事半功倍的效果。

模式 描述
^ 匹配字符串的开头
$ 匹配字符串的末尾。
. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[…] 用来表示一组字符,单独列出:[amk] 匹配 ‘a’,‘m’或’k’
[^…] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re* 匹配0个或多个的表达式。
re+ 匹配1个或多个的表达式。
re? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{n} 匹配n个前面表达式。例如,"o{2}“不能匹配"Bob"中的"o”,但是能匹配"food"中的两个o。
re{n,} 精确匹配n个前面表达式。例如,"o{2,}“不能匹配"Bob"中的"o”,但能匹配"foooood"中的所有o。"o{1,}“等价于"o+”。"o{0,}“则等价于"o*”。
re{n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
| 匹配a或b
(re) 匹配括号内的表达式,也表示一个组
(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re) 类似 (…), 但是不表示一个组
(?imx: re) 在括号中使用i, m, 或 x 可选标志
(?-imx: re) 在括号中不使用i, m, 或 x 可选标志
(?#…) 注释.
(?= re) 前向肯定界定符。如果所含正则表达式,以 … 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。
(?> re) 匹配的独立模式,省去回溯。
\w 匹配数字字母下划线
\W 匹配非数字字母下划线
\s 匹配任意空白字符,等价于 [\t\n\r\f]。
\S 匹配任意非空字符
\d 匹配任意数字,等价于 [0-9]。
\D 匹配任意非数字
\A 匹配字符串开始
\Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。
\z 匹配字符串结束
\G 匹配最后匹配完成的位置。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。
\B 匹配非单词边界。‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。
\n, \t, 等 匹配一个换行符。匹配一个制表符, 等
\1…\9 匹配第n个分组的内容。
\10 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。

1.字符匹配

方法和功能

方法 功能
match() 判断一个正则表达式是否从开始处匹配一个字符串
search() 遍历字符串,找到正则表达式匹配的第一个位置,返回匹配对象
findall() 遍历字符串,找到正则表达式匹配的所有位置,并以列表的形式返回。如果给出的正则表达式中包含子组,就会把子组的内容单独返回,如果有多个子组就会以元组的形式返回。
finditer() 遍历字符串,找到正则表达式匹配的所有位置,并以迭代器的形式返回
  • hqyj匹配文本中的hqyj
import re
text="hqyj牛皮6666,hqyj有个老师也牛皮666"
data=re.findall("hqyj",text)
print(data)#['hqyj', 'hqyj']
  • [hqyj]匹配h或者q或者y或者j字符
import re
text="hqyj牛皮6666,hqyj有个老师也牛皮666"
data=re.findall("[hqyj]",text)
print(data)#['h', 'q', 'y', 'j', 'h', 'q', 'y', 'j']
import re
text="hqyj牛皮6666,hqyj有个老师也牛皮666"
data=re.findall("[hqyj]牛",text)
print(data)#['j牛']
  • [^hqyj]匹配除了hqyj以外的其他字符
import re
text="hqyj牛皮6666,hqyj有个老师也牛皮666"
data=re.findall("[^hqyj]",text)
print(data)#['牛', '皮', '6', '6', '6', '6', ',', '有', '个', '老', '师', '也', '牛', '皮', '6', '6', '6']

  • [a-z]匹配a~z的任意字符([0-9]也可以)
import re
text="hqyj牛皮6666,hqyj有个老师abchqyj也牛皮666"
data=re.findall("[a-z]hqyj",text)
print(data)#['chqyj']
  • .匹配除了换行符以外的任意字符
import re
text="hqyj牛皮6666,hqyj有个老师abchqyj也牛皮666"
data=re.findall(".hqyj",text)
print(data)#[',hqyj', 'chqyj']
import re
text="hqyj牛皮6666,hqyj有个老师abchqyj也牛皮666"
data=re.findall(".+hqyj",text) #贪婪匹配(匹配最长的)
print(data)#['hqyj牛皮6666,hqyj有个老师abchqyj']
import re
text="hqyj牛皮6666,hqyj有个老师abchqyj也牛皮666"
data=re.findall(".?hqyj",text)
print(data)#['hqyj', ',hqyj', 'chqyj']

特殊字符

特殊字符 含义
\d 匹配任何十进制数字;相当于类 [0-9]
\D 与 \d 相反,匹配任何非十进制数字的字符;相当于类 [^0-9]
\s 匹配任何空白字符(包含空格、换行符、制表符等);相当于类 [ \t\n\r\f\v]
\S 与 \s 相反,匹配任何非空白字符;相当于类 [^ \t\n\r\f\v]
\w 匹配任意一个文字字符,包括大小写字母、数字、下划线,等价于表达式[a-zA-Z0-9_]
\W 于 \w 相反 (注:re.ASCII 标志使得 \w 只能匹配 ASCII 字符)
\b 匹配单词的开始或结束
\B 与 \b 相反
  • \w 匹配字母数字下划线(汉字)
import re
text="华清_远见abc 华清hqyj远见 华清牛皮远见"
data=re.findall("华清\w+远见",text)
print(data)#['华清_远见', '华清hqyj远见', '华清牛皮远见']
  • \d匹配数字
import re
text="hqyj66d6 a1h43d3fd43s43d4 "
data=re.findall("d\d",text) # 只匹配一个数字
print(data)#['d6', 'd3', 'd4', 'd4']
import re
text="hqyj66d6 a1h43d3fd43s43d4 "
data=re.findall("d\d+",text)
print(data)#['d6', 'd3', 'd43', 'd4']
  • \s匹配任意空白符 包括空格,制表符等等
import re
text="hqyj666  jack karen 666"
data=re.findall("\sj\w+\s",text)
print(data)#[' jack ']

2.数量控制

*重复0次或者更多次

import re
text="华清远见 华清666远见"
data=re.findall("华清6*远见",text)
print(data)#['华清远见', '华清666远见']

+重复1次或者更多次

import re
text="华清远见 华清666远见 华清6远见"
data=re.findall("华清6+远见",text)
print(data)#['华清666远见', '华清6远见']

?重复1次或者0次

import re
text="华清远见 华清666远见 华清6远见"
data=re.findall("华清6?远见",text)
print(data)#['华清远见', '华清6远见']

{n}重复n次,n是数字

import re
text="华清远见 华清666远见 华清6远见"
data=re.findall("华清6{3}远见",text)
print(data)#['华清666远见']

{n,}重复n次或者更多次

import re
text="华清远见 华清666远见 华清6远见 华清66远见"
data=re.findall("华清6{2,}远见",text)
print(data)#['华清666远见', '华清66远见']

{n,m}重复n到m次

import re
text="华清远见 华清666远见 华清6远见 华清66远见"
data=re.findall("华清6{0,2}远见",text)
print(data)#['华清远见', '华清6远见', '华清66远见']

3.分组

  • ()提取兴趣区域
import re
text="谢帝谢帝,我要迪士尼,我的电话号码18282832341,qq号码1817696843"
data=re.findall("号码(\d{10,})",text)
print(data)#['18282832341', '1817696843']
import re
text="谢帝谢帝,我要迪士尼,我的电话号码18282832341,qq号码1817696843"
data=re.findall("(\w{2}号码(\d{10,}))",text)
print(data)#['18282832341', '1817696843']
  • (|)提取兴趣区域(| = or)
import re
text="第一名张三 第一名物理149分 第一名数学150分 第一名英语148分 第一名总分740分"
data=re.findall("第一名(\w{2,}|\w{2,}\d{2,}分)",text)
print(data)#['张三', '物理149分', '数学150分', '英语148分', '总分740分']

4.开始和结束

  • ^开始
import re
text = "hqyj66abc hqyj123"
data = re.findall("^hqyj\d+", text)
print(data)  #['hqyj66']
  • $结尾
import re
text = "hqyj66abc hqyj123"
data = re.findall("hqyj\d+$", text)
print(data)  #['hqyj123']

5.特殊字符

由于正则表达式中* . \ {} () 等等符号具有特殊含义,如果你指定的字符正好就是这些符号,需要用\进行转义

import re
text = "数学中集合的写法是{2}"
data = re.findall("\{2\}", text)
print(data)  #['{2}']

6.re模块的常用方法

re.findall

获取匹配到的所有数据

import re
text="hqyj66d6 a1h43d3fd43s43d4 "
data=re.findall("d\d+",text)
print(data)#['d6', 'd3', 'd43', 'd4']

re.match

从字符串的起始位置匹配,成功返回一个对象否则返回none。

匹配成功返回对象,对象的方法:

方法 功能
group() 返回匹配的字符串
start() 返回匹配的开始位置
end() 返回匹配的结束位置
span() 返回一个元组表示匹配位置(开始,结束)
import re

# 在起始位置匹配,并返回一个包含匹配 (开始,结束) 的位置的元组
print(re.match('www', "www.python.com").span())#(0, 3)
print(re.match('www', "www.python.com").start())#0
print(re.match('www', "www.python.com").end())#3
# 不在起始位置匹配
print(re.match('com', "www.python.com"))# None

re.search

扫描整个字符串并返回第一个成功匹配的字符串。成功返回一个对象否则返回none

import re

# 在起始位置匹配 
print(re.search('www', 'www.hqyj.com').span())#(0, 3)
# 不在起始位置匹配
print(re.search('com', 'www.hqyj.com').span())#(9, 12)

re.sub

替换匹配成功的字符

类似与字符串的replace函数

import re
text = "以前华清远见在四川大学旁边,现在华清远见在西南交大旁边"
data = re.sub("华清远见","北京华清远见科技集团成都中心", text)
print(data)#以前北京华清远见科技集团成都中心在四川大学旁边,现在北京华清远见科技集团成都中心在西南交大旁边

re.split

根据匹配成功的位置对字符串进行分割

import re
text = "python is   very easy"
data = re.split("\s{1,}", text)
print(data)#['python', 'is', 'very', 'easy']

re.finditer

类似findall 但是不会全部返回出来 而是返回迭代器(比如匹配成功了10万个 全部返回就很吃内存了)

import re
text = "python is   very easy"
data = re.findall("\w+", text)
print(data)#['python', 'is', 'very', 'easy']
import re
text = "python is   very easy"
data = re.finditer("\w+", text)
print(data)
for el in data:
    print(el.group())

7.常见的一些正则

QQ号:[1 - 9][0 - 9]{4, }(腾讯QQ号从10000开始)
帐号(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
身份证号(15位、18位数字):^\d{15}|\d{18}$
短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$

Python日期和时间

Python 的 time 模块下有很多函数可以转换

  • 常见日期格式。

time 模块时间处理的和转换时间格式的常用API: [官网链接](time — 时间访问和转换 — Python 3.12.2 文档)

time.time() - 获取当前时间的时间戳(以秒为单位,浮点数形式,精确到小数点后若干位)

import time  # 引入time模块

ticks = time.time()
print ("当前时间戳为:", ticks)#时间戳单位最适于做日期运算。但是1970年之前的日期就无法以此表示了。太遥远的日期也不行,UNIX和Windows只支持到2038年

time.sleep(secs) - 让程序暂停执行指定秒数。

import time

# 让程序暂停3秒
time.sleep(3)
print("3秒后执行到这里...")

time.ctime(timestamp=None) - 将时间戳转换为易读的本地时间格式。

import time

# 获取当前时间的ctime格式
current_time = time.ctime()
print("当前时间 (ctime):", current_time)

# 或者使用特定时间戳
timestamp = 1647708000  # 这是一个示例时间戳
converted_time = time.ctime(timestamp)
print("时间戳转ctime格式:", converted_time)

time.localtime([secs]) - 将时间戳转换为本地时区的struct_time元组。

import time

# 获取当前时间的struct_time元组
local_time_tuple = time.localtime()
print("当前时间 (struct_time):", local_time_tuple)

# 或者使用特定时间戳
timestamp = time.time()
converted_tuple = time.localtime(timestamp)
print("时间戳转struct_time:", converted_tuple)

time.strftime(format[, t]) - 格式化本地时间。

import time

# 获取当前时间并格式化为“年-月-日 时:分:秒”
formatted_time = time.strftime('%Y-%m-%d %H:%M:%S')
print("格式化当前时间:", formatted_time)

# 使用特定时间戳
timestamp = time.time()
custom_format = time.strftime("%Y%m%d_%H%M%S", time.localtime(timestamp))
print("格式化后的时间戳:", custom_format)

格式化符号:

  • %y 两位数的年份表示(00-99)
  • %Y 四位数的年份表示(000-9999)
  • %m 月份(01-12)
  • %d 月内中的一天(0-31)
  • %H 24小时制小时数(0-23)
  • %I 12小时制小时数(01-12)
  • %M 分钟数(00=59)
  • %S 秒(00-59)
  • %a 本地简化星期名称
  • %A 本地完整星期名称
  • %b 本地简化的月份名称
  • %B 本地完整的月份名称
  • %c 本地相应的日期表示和时间表示
  • %j 年内的一天(001-366)
  • %p 本地A.M.或P.M.的等价符
  • %U 一年中的星期数(00-53)星期天为星期的开始
  • %w 星期(0-6),星期天为星期的开始
  • %W 一年中的星期数(00-53)星期一为星期的开始
  • %x 本地相应的日期表示
  • %X 本地相应的时间表示
  • %Z 当前时区的名称
  • %% %号本身

属性(time模块本身没有属性,但可以通过其提供的函数生成的对象来访问属性)

对于struct_time对象(由time.localtime()或time.gmtime()等返回),它是一个元组,可以按索引访问各个时间元素:

属性
tm_year
tm_mon 月:1 到 12
tm_mday 日:1 到 31
tm_hour 时:0 到 23
tm_min 分:0 到 59
tm_sec 秒:0 到 61 (60或61 是闰秒)
tm_wday 星期:0 到 6 (0是周一)
tm_yday 一年中的第几天,1 到 366
tm_isdst 是否为夏令时,值有:1(夏令时)、0(不是夏令时)、-1(未知),默认 -1
import time

local_time = time.localtime()

# 访问struct_time的属性(索引)
year = local_time.tm_year
month = local_time.tm_mon
day = local_time.tm_mday
hour = local_time.tm_hour
minute = local_time.tm_min
second = local_time.tm_sec
print(f"当前日期和时间:{
      
      year}-{
      
      month}-{
      
      day} {
      
      hour}:{
      
      minute}:{
      
      second}")

Python网络

Python requests 是一个常用的 HTTP 请求库,可以方便地向网站发送 HTTP 请求,并获取响应结果。

使用 requests 发送 HTTP 请求需要先下载并导入 requests 模块:

import requests

# 导入 requests 包
import requests
response = requests.get('https://www.baidu.com')# 发送请求
print(response.content)  # 获取响应内容


response2 = requests.get('http://localhost:7001/test')# 发送请求
print(response2.json())  # 获取json数据并解析

每次调用 requests 请求之后,会返回一个 response 对象,该对象包含了具体的响应信息,如状态码、响应头、响应内容等:

response的属性或方法 说明
apparent_encoding 编码方式
close() 关闭与服务器的连接
content 返回响应的内容,以字节为单位
cookies 返回一个 CookieJar 对象,包含了从服务器发回的 cookie
elapsed 返回一个 timedelta 对象,包含了从发送请求到响应到达之间经过的时间量,可以用于测试响应速度。比如 r.elapsed.microseconds 表示响应到达需要多少微秒。
encoding 解码 r.text 的编码方式
headers 返回响应头,字典格式
history 返回包含请求历史的响应对象列表(url)
is_permanent_redirect 如果响应是永久重定向的 url,则返回 True,否则返回 False
is_redirect 如果响应被重定向,则返回 True,否则返回 False
iter_content() 迭代响应
iter_lines() 迭代响应的行
json() 返回结果的 JSON 对象 (结果需要以 JSON 格式编写的,否则会引发错误)
links 返回响应的解析头链接
next 返回重定向链中下一个请求的 PreparedRequest 对象
ok 检查 “status_code” 的值,如果小于400,则返回 True,如果不小于 400,则返回 False
raise_for_status() 如果发生错误,方法返回一个 HTTPError 对象
reason 响应状态的描述,比如 “Not Found” 或 “OK”
request 返回请求此响应的请求对象
status_code 返回 http 的状态码,比如 404 和 200(200 是 OK,404 是 Not Found)
text 返回响应的内容,unicode 类型数据
url 返回响应的 URL

requests的方法

方法 描述
delete(url, args) 发送 DELETE 请求到指定 url
get(url, params, args) 发送 GET 请求到指定 url
head(url, args) 发送 HEAD 请求到指定 url
patch(url, data, args) 发送 PATCH 请求到指定 url
post(url, data, json, args) 发送 POST 请求到指定 url
put(url, data, args) 发送 PUT 请求到指定 url
request(method, url, args) 向指定的 url 发送指定的请求方法

requests.get(url, params ={key: value}, args)

  • url 请求 url。
  • **params ** 参数为要发送到指定 url 的 JSON 对象。
  • args 为其他参数,比如 cookies、headers、verify等。
import requests

# 图片URL地址
image_url = 'http://localhost:7001/public/1.png'

# 发送GET请求获取图片数据
response = requests.get(image_url)

# 检查请求是否成功(HTTP状态码为200)
if response.status_code == 200:
    # 将图片数据写入本地文件
    with open('image.jpg', 'wb') as f:
        f.write(response.content)
    print("图片已成功下载并保存为 image.jpg")
else:
    print(f"无法下载图片,响应状态码:{
      
      response.status_code}")

requests.post(url, data={key: value}, json={key: value}, args)

  • url 请求 url。
  • data 参数为要发送到指定 url 的字典、元组列表、字节或文件对象。
  • json 参数为要发送到指定 url 的 JSON 对象。
  • args 为其他参数,比如 cookies、headers、verify等。
import requests
headers = {
    
    'User-Agent': 'Mozilla/5.0'}  # 设置请求头
params = {
    
    'key1': 'value1', 'key2': 'value2'}  # 设置查询参数
data = {
    
    'username': 'jack', 'password': '123456'}  # 设置请求体
response = requests.post('http://localhost:7001/test', headers=headers, params=params, data=data)
print(response.text)

猜你喜欢

转载自blog.csdn.net/b227737437/article/details/143368867