python常用库

常见模块解析

1. math库

数学函数
函数返回值 ( 描述 )
abs(x)返回数字的绝对值,如abs(-10) 返回 10
ceil(x)返回数字的上入整数,如math.ceil(4.1) 返回 5
cmp(x, y)如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1。 **Python 3 已废弃,使用 (x>y)-(x。
exp(x)返回e的x次幂(ex),如math.exp(1) 返回2.718281828459045
fabs(x)返回数字的绝对值,如math.fabs(-10) 返回10.0
floor(x)返回数字的下舍整数,如math.floor(4.9)返回 4
log(x)如math.log(math.e)返回1.0,math.log(100,10)返回2.0
log10(x)返回以10为基数的x的对数,如math.log10(100)返回 2.0
max(x1, x2,…)返回给定参数的最大值,参数可以为序列。
min(x1, x2,…)返回给定参数的最小值,参数可以为序列。
modf(x)返回x的整数部分与小数部分,两部分的数值符号与x相同,整数部分以浮点型表示。
pow(x, y)x**y 运算后的值。
round(x [,n])返回浮点数 x 的四舍五入值,如给出 n 值,则代表舍入到小数点后的位数。其实准确的说是保留值将保留到离上一位更近的一端。
sqrt(x)返回数字x的平方根。

三角函数

Python的math库包括以下三角函数:(比如:math.sin(math.pi/2))

函数描述
acos(x)返回x的反余弦弧度值。
asin(x)返回x的反正弦弧度值。
atan(x)返回x的反正切弧度值。
atan2(y, x)返回给定的 X 及 Y 坐标值的反正切值。
cos(x)返回x的弧度的余弦值。
hypot(x, y)返回欧几里德范数 sqrt(xx + yy)。
sin(x)返回的x弧度的正弦值。
tan(x)返回x弧度的正切值。
degrees(x)将弧度转换为角度,如degrees(math.pi/2) , 返回90.0
radians(x)将角度转换为弧度

数学常量
常量描述
math.pi数学常量 pi(圆周率,一般以π来表示)
math.e数学常量 e,e即自然常数(自然常数)。

2. random库

Python的random库包含以下常用随机数函数:

import random
# 生成一个 [0, 1) 范围内的随机小数
print(random.random())

# 生成一个 [1, 10] 范围内的随机整数
print(random.randint(1, 10))

# 生成一个 [0, 1] 范围内的随机小数
print(random.uniform(0, 1))

# 从序列中随机选择一个元素
seq = ['apple', 'banana', 'orange']
print(random.choice(seq))

# 将序列中的元素随机打乱(shuffle洗牌)
seq = [1, 2, 3, 4, 5]
random.shuffle(seq)
print(seq)

3. re 模块

1. 常用正则表达式
模式描述
\w匹配字母数字及下划线
\W匹配非字母数字下划线
\s匹配任意空白字符,等价于[\t,\n,\r,\f]
\S匹配任意非空字符
\d匹配任意数字,等价于[0-9]
\D匹配任意非数字
\A匹配以xx字符串开始
\Z匹配xx字符串结束,如果是存在换行,只匹配到换行前的结束字符串
\z匹配xx字符串结束
\G匹配最后匹配完成的位置
\n匹配一个换行符
\t匹配一个制表符
^匹配字符串的开头
$匹配字符串的末尾
.匹配任意字符, 除了换行符, 当 re.DOTALL 标记被指定时, 则可以匹配包括换行符的任意字符
[…]用来表示一组字符, 单独列出:[amk] 匹配 ‘a’,‘m’ 或 ‘k’
[^…]不在 [ ] 中的字符:[^abc] 匹配除了a, b, c之外的字符
*匹配0个或多个的表达式
+匹配1个或多个的表达式
?匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
{n}精确匹配n个前面表达式。
{n,m}匹配n到m次由前面的正则表达式定义的片段,贪婪方式
alb匹配a或b
()匹配括号内的表达式,也表示一个组

注意[ ]所有的特殊字符在字符集中都失去其原有的特殊含义,在字符集中如果要使用]-^,可以在前面加上反斜杠,或把]-放在第一个字符,把^放在非第一个字符

2. 常用函数
函数说明
re.match( )从字符串的起始位置匹配, 匹配成功, 返回一个匹配的对象, 否则返回None
re.search( )扫描整个字符串并返回第一个成功的匹配
re.findall( )在字符串中找到正则表达式所匹配的所有子串, 并返回一个列表, 如果没有找到匹配的, 则返回空列表
re.split( )将一个字符串按照正则表达式匹配结果进行分割, 返回列表类型
re.finditer( )在字符串中找到正则表达式所匹配的所有子串, 并把它们作为一个迭代器返回
re.sub( )把字符串中所有匹配正则表达式的地方替换成新的字符串
re.complie( )将正则表达式传入, 返回一个匹配对象, 一般与其他方法组合使用
3. 正则匹配使用示例
print("hello".replace("llo","ooo"))  # heooo
print("hello".find("abcd"))  # -1 (找不到返回 -1)
print("hello".find("he"))    # 0

import re
print(re.findall("\w","ab* 12$ _"))  # ['a', 'b', '1', '2', '_']
print(re.findall("\s","ab* 12$ _ "))  # [' ', ' ', ' ']
print(re.findall("\Aab","ab* 12$ _"))  # ['ab']
print(re.findall("\Aaa","ab* 12$ _"))  # [] 没匹配到为空
print(re.findall("_\Z","ab* 12$ _"))   # ['_']
print(re.findall("0\Z","ab* 12$ _"))   # [] 没匹配到为空
print(re.findall("\t","ab* 12$ \t_"))    # ['\t']
#"\s" 可以匹配"\t"和"\n"
print(re.findall("^ab","ab* 12$ _"))   # ['ab']
print(re.findall("_$","ab* 12$ _\n"))  # ['_']

重复匹配

#.匹配任意一个字符
import re
print(re.findall("a.b","a\tb")) # ['a\tb']
print(re.findall("a.b","a\nb")) # [] (换行符匹配不到,匹配为空)
print(re.findall("a.b","a b a*b abb a_b")) # ['a b', 'a*b', 'abb', 'a_b']
print(re.findall("a.b","a\nb",re.S))     # ['a\nb'] (加入参数, 包含换行)
print(re.findall("a.b","a\nb",re.DOTALL))   # ['a\nb'] (同上效果一样)

#* 匹配前面那个字符0个或者n个
print(re.findall("a*","aaaa aa"))# ['aaaa', '', 'aa', ''] (零个或多个a)
print(re.findall("ab*","abab aa"))# ['ab', 'ab', 'a', 'a'] (一个a零个或多个b)
print(re.findall("a*b","ababaaaba aa")) # ['ab', 'ab', 'aaab'] (零个或多个a一个b)
print(re.findall("ab*","bbbbbbbb"))  # [] (没有匹配到一个a零个或多个b)

#? 匹配前面那个字符0个或者1个
print(re.findall("ab?","a"))     # ['a'],匹配1个a,0个b
print(re.findall("ab?","abbb"))  # ['ab']

#{n,m} 匹配n~m个
print(re.findall("a{2}","aaaa"))     # ['aa', 'aa']
print(re.findall("ab{2,6}","abbb"))  # ['abbb'] (一个a,2~6个b)
print(re.findall("ab{1,}","abbb"))   # ['abbb'] (相当于 ab+)
print(re.findall("ab{0,}","abbb"))   # ['abbb'] (相当于 ab*)

#[ ]逐个匹配
print(re.findall("a[*1_c-]b","a*ba1b a_baaba-b")) # ['a*b', 'a1b', 'a_b', 'a-b']
print(re.findall("a[^a-zA-Z0-9]b","a*banb aPbaa7b"))  # ['a*b'] (非a~z,A~Z,0~9)

#( )分组
print(re.findall('ab+','ababab123')) # ['ab', 'ab', 'ab']
print(re.findall('(ab)+123','ababab123')) # ['ab'],匹配到末尾的 ab123 中的 ab
print(re.findall('(?:ab)+123','ababab123')) 
#['ababab123'], findall的结果不是匹配的全部内容,而是组内的内容, ?: 可以让结果为匹配的全部内容,详见非捕获匹配
print(re.findall('href="(.*?)"','<a href="http://www.baidu.com">点击</a>'))# ['http://www.baidu.com']
print(re.findall('href="(?:.*?)"','<a href="http://www.baidu.com">点击</a><a href="http://www.aiqiyi.com">点击2</a>'))
# ['href="http://www.baidu.com"', 'href="http://www.aiqiyi.com"']


print(re.findall("a\.b","a1b a.b"))  # ['a.b']
print(re.findall("shawn|song","shawn is man song is shawn"))  # ['shawn', 'song', 'shawn']
print(re.findall("A(?:abc|cba)A","AabcA"))  # ['AabcA']
print(re.findall("com(?:puter|e)","come on! Here is a computer "))  # ['come', 'computer']

#匹配所有数字
print(re.findall("\d+\.?\d*","12as3.45qw2k7"))  # ['12', '3.45', '2', '7']

贪婪匹配.*与懒惰匹配.*?

print(re.findall("a.*b","a11b22222b33"))  # ['a11b22222b']
print(re.findall("a.*?b","a11b22222b3"))  # ['a11b']
4. 方法示例
#re.findall(pattern,string)
	#在字符串中找到正则表达式所匹配的所有子串, 并返回一个列表, 如果没有找到匹配的, 则返回空列表
print(re.findall("(ab)+(cd)+","ababcdcd abcd"))
	#[('ab', 'cd'), ('ab', 'cd')],返回元组列表

#re.search()
	匹配整个字符串, 只到找到第一个匹配然后返回一个包含匹配信息的对象(re.Match对象)
	该对象可以通过调用 group()方法得到匹配的字符串,如果字符串没有匹配,则返回None
	如果没有匹配到值就调用 group() 方法, 抛出异常
print(re.search("abc","112abc333abc"))  
	# <re.Match object; span=(3, 6), match='abc'>
print(re.search("abc","112abc333abc").group())  # abc

print(re.search("abcd","12abc333abc"))          # None
print(re.search("abcd","12abc333abc").group()) 
	# 报错 "AttributeError" 因为没拿到这个对象,所以没有group()属性

#re.match()
	与 re.search 功能相同, 但必须匹配起始位置, 不然返回 None
print(re.match("abc","abc22abc"))  
	# <re.Match object; span=(0, 3), match='abc'>
print(re.match("abc","abc22abc").group())  # abc
print(re.match("abc","1abc22abc"))  # None

#re.split()
	以规定字符作为分隔符对字符串进行切分, 切分结果放入列表, 没匹配到返回原字符串列表
    将规定字符放入 [ ] 则是逐个匹配
print(re.split("ab","abcoababcoabc"))  #['', 'co', '', 'co', 'c']
print(re.split("a","nbc")) #['nbc'],返回原字符串
print(re.split("[ob]","abcoabcoabc"))  # ['a', 'c', 'a', 'c', 'a', 'c']

#re.sub()和re.subn()
	匹配字符, 并将其该成指定字符, 返回改变后的字符串, 后面可跟个数参数, 不指定默认替换所有
	re.subn( ) 返回一个元组, 第二个元素返回的是替换的个数
print(re.sub("a","AA","i am a man"))  # i AAm AA mAAn
print(re.sub("a","AA","i am a man",100))  # i AAm AA mAAn,不报错
print(re.subn("a","A","i am a man"))  # ('i Am A mAn', 3) (显示替换的个数)

#re.compile()  	返回一个对象
obj=re.compile("\d{2}")
print(obj) # re.compile('\\d{2}')
print(obj.findall("ab123bc123")) #['12', '12']
print(obj.search("ab123bc123").group())	# 12
print(obj.match("123ab123bc123").group())	# 12

substitude 替换

5. 非捕获匹配?: ?! ?=

在这里插入图片描述

# ?:
	(?:)非捕获分组,只会进行单纯的模式匹配并不会将匹配到的值进行保存,与()区分
print(re.findall("jk(loli)+","jkloli")) # ['loli']
print(re.findall("jk(?:loli)+","jkloli")) # ['jkloli']

# ?!	正向否定预查
	1.在没匹配到字符串的前提下,再进行后续的正则,后续匹配仍然从被匹配字符串的头开始
res = re.match("(?![\d]+$)(?![a-zA-Z]+$)[\da-zA-Z]{6}$",passwd)
	#匹配6位数字与字母组合,不能纯数字或字母
    2.匹配位置 后面 不能跟着指定表达式。
print(re.findall("19(?!99)","1999"))
print(re.findall("\d{2}(?!99)","1999 1988"))#['99', '19', '88']
	#先尝试匹配"1999",再'999 '(成功),再"9 19",再" 198",再"1988"(成功),再"88",理解下匹配的窗格移动
    
# ?=  正向肯定预查
	1.在匹配到字符串的前提下,再进行后续的正则,后续匹配仍然从被匹配字符串的头开始
res = re.search("(?=.*[\d])(?=.*[a-z])(?=.*[A-Z])(?=.*)(?=.*[!@#%&])^([\da-zA-Z!@#%&]{7,})$",passwd)
	#至少七位密码,包含大小写,数字,特殊字符(!,@,#,%,&)
    
    2.匹配位置 后面 必须跟着指定表达式。
r"foo(?=bar)"可以匹配foobar中的foo,不能匹配foobaz中的foo
    

# ?<=
	匹配位置 前面 必须跟着指定表达式。
print(re.findall("(?<=jk).*?(?=li)","mcjli jkloli liejk"))   #['lo']

# ?<!
	匹配位置 前面 不能跟着指定表达式。
	print(re.findall("\\B(?<!18)\d{2}\\b","1988  1899")) #['88']
	
6. 边界匹配问题

\b表示单词边界,\B表示非单词边界

一般空格、换行、标点符号或者特殊符号来表示边界

或者说非数字、字母、下滑线、unicode汉字表示边界

中文字符串为边界的话要用re.A编码模式

print(re.findall("\\b19(?:[^9]{2})\\b","1999  1988")) #['1988']

print(re.findall("\\b19(?:[^9]{2})\\b","你也玩1999?1988带我一个",re.A))
	# ['1988']

4. requests库

基于urllib库的HTTP库,比urllib库方便。

超文本传输协议(HTTP)是一种基于"请求与响应"模式的、无状态的应用层协议。

URL一般格式
protocol://host[:port]/path/[?query]#fragment
http://www.itcast.cn/index.html?name=andy&age=18#link

GET与POST区别

使用:GET通常用于获取网页数据,查询数据等,POST通常用于提交表单,上传文件等。

安全性:GET请求将参数附加在URL中,对用户可见。POST请求的参数包含在请求体中,对用户不可见。

请求长度限制:GET请求将参数附加到URL中,URL的长度有限制。POST请求将参数包含在请求体中,可以传递较大数据量。

缓存:GET请求可以被缓存,POST请求不会被缓存。

对数据类型的限制:GET只允许ASCII字符,POST允许二进制数据。

requests库常用方法
r=requests.get(url, params=None, **kwargs)get请求,params得是一个字典,kwargs一般有headers请求头
r=requests.post(url, data=None, json=None, **kwargs)post请求,data得是一个字典
r=requests.Session()使用Session类维持会话
常见可变参数
headers请求头
cookies设cookie来维持登陆状态
proxies代理设置
files用来post上传文件
timeout=60连接和读取总超时时间(秒)
auth=(‘admin’,‘123’)身份验证
response的属性
r.status_codehttp请求的返回状态,若为200则表示请求成功。
r.cookies.items()获取cookies,用key,value遍历
r.texthttp响应内容的字符串形式,即返回的页面内容
r.contenthttp响应内容的二进制形式
r.json()得到对应的json格式
r.encoding从http header 中猜测的相应内容编码方式
r.apparent_encoding从内容中分析出的响应内容编码方式(备选编码方式)
f={'file':'open('1.jpg',"rb")'}
proxies={
    'http':'http://127.0.0.1:80',
    # 'https':'https://127.0.0.1:80',
    'https':'socks5://user:password@192.168.123.1:80'
}
r=requsets.post("http://baidu.com/",files=f,proxies=proxies)
import requests
import os
from urllib import parse
string={'t':'1','from':'0','comm_exist':'on','kw':"月星中央公园"}
string=parse.urlencode(string)# url编码一下
cookie="ctid=39; aQQ_ajkguid=48F4121D-3F8D-0077-F423-82558C46ABD7; id58=CrIclWU30oyGjaJ4LaR6Ag==; ajk-appVersion=; seo_source_type=1; fzq_h=475856ba31bb9179139bb04430940fd8_1705814357915_34bf968494bc41539dea738e0278cf08_2028294646; lp_lt_ut=26f889a16be9d3724fab580f7353e7b0; isp=true; 58tj_uuid=74bed1ad-98fe-4120-91e6-0ee5e400d6c1; new_uv=1; als=0; xxzlclientid=4c186e92-9252-49e3-a441-1705816054130; xxzlxxid=pfmxQcvbGG0JAmeSXOHwuGZagiOoTmFdcwnahVpL/gL6nPEOcXjJIPev+Dr7CvHH9VmI; xxzlbbid=pfmbM3wxMDMyNXwxLjUuMXwxNzA1OD…mctid=188; sessid=75FB0FE2-B6E9-87EA-661E-10DEDA44EEBD; obtain_by=1; twe=2; fzq_js_anjuke_ershoufang_pc=05ed67efa31983351a3cde4b55d7acba_1705819197158_24; lps=https%3A%2F%2Fshen.zu.anjuke.com%2F%3Fkw%3D%25E6%259C%2588%25E6%2598%259F%25E4%25B8%25AD%25E5%25A4%25AE%25E5%2585%25AC%25E5%259B%25AD%26comm_exist%3Don%26from%3Dlist_ac%26facet_comm_id%3D100668077%7Chttps%3A%2F%2Fsy.anjuke.com%2F; xxzl_cid=676c948039454a4b851884286e2878df; xxzl_deviceid=W69KvVyR07t3zIA7fgB7dplSWQbqPXDJr9UgO+3mZe1z643gASf+/vurnxxXytg7"
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
'Host':'shen.zu.anjuke.com',
'Cookie':cookie.encode('utf-8') # cookie有些字符没法识别,需要编码一下
         }
r=requests.get("https://shen.zu.anjuke.com/?",params=string,headers=headers)
print(r.status_code)# 状态码
r.encoding=r.apparent_encoding # apparent_encoding会从内容中分析出响应内容编码
# r.encoding="gb2312" 或者手动赋值防止中文乱码
content=r.text
if not os.path.exists('./test1.txt'):
    open('./test1.txt','w').close()# 新建txt
with open('./test1.txt','w+') as fp: # 这边是读写形式新建(或覆盖)一个文件
    fp.write(content)

5. threading库

1. 基本概念

Thread类的构造方法

def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None):

类与方法作用
Thread(target,args,kwargs)Thread类,target线程函数,args是传递给目标函数的参数,kwargs关键字参数
start()启动线程,调用线程的run()方法来执行线程函数。
join(timeout)等待线程执行完毕再执行后面代码,可选地指定一个超时时间。
is_alive()返回线程是否处于活动状态
getName()返回线程的名称
setName(name)设置线程的名称
sleep(seconds)在指定的秒数内让线程休眠
enumerate()返回当前活动的Thread对象列表
current_thread()返回当前线程对象
active_count()当前活动线程数量
属性
name线程名称
is_alive线程是否处于活动状态
ident线程的标识符
import threading
import time
l=["a","b","c"]
def task(e):
    print("线程名%s,参数%s"%(threading.current_thread().name,e))    
    print("id:%s"%(threading.current_thread().ident))
    time.sleep(5)
if __name__=='__main__':
    for i in l:
        t=threading.Thread(target=task,args=(i,))# 创建线程
        t.start() # 启动线程      
print(f"{threading.current_thread().name}")# MainThread # 主线程
print(f"{threading.active_count()}") # 4 # 包含了主线程

在这里插入图片描述

2. daemon 守护线程

设为True的时候,当主程序执行完成后,马上就终止当前任务,不管是否完成。

在这里插入图片描述

设为None的时候(默认),当主程序执行完成后,会等待子线程完成再退出。

在这里插入图片描述

import threading
import time
l=["a","b","c"]
def task(e):
    c=threading.current_thread()
    print("线程名%s,参数%s"%(c.name,e))
    time.sleep(2)
    print("线程名%s,id:%s"%(c.name,c.ident))

if __name__=='__main__':
    for i in l:
        t=threading.Thread(target=task,args=(i,),daemon=None)
        t.start() # 启动线程
print(f"{threading.current_thread().name}")
print(f"{threading.active_count()}") 
3. 线程间的等待join

在这里插入图片描述

import threading
import time
l=["a","b","c","d"]
def task(e):
    c=threading.current_thread()
    print("线程名%s,参数%s"%(c.name,e))
    time.sleep(2)
    print("线程名%s,id:%s"%(c.name,c.ident))
threads=[]
if __name__=='__main__':
    for i in l:
        t=threading.Thread(target=task,args=(i,))
        t.start() # 启动线程
        threads.append(t)
for i in threads:
    i.join()# 当threads[0]线程执行完后才会遍历threads[1]线程,以此类推
    # 但是sleep阻塞结束后,线程调度将自行选择一个线程执行,没法保证顺序
print("结束")
4. Lock 锁解决资源竞争问题(丢失更新)

在这里插入图片描述

import threading
num=100
num2=200000
count=0
lock=threading.Lock() # 新建锁对象
threads=[]
def task():
    global count
    for i in range(num2):
        #with lock:
        lock.acquire()# 获取锁
        count+=1
        lock.release()# 释放锁
if __name__=='__main__':
    for i in range(num):
        t=threading.Thread(target=task)
        t.start() # 启动线程
        threads.append(t)
    for i in threads:
        i.join()# 线程的结束顺序是乱序的,必须等全部结束才打印
    print(f"{count}")# 20000000,结果要等很久
5. 线程终止
import ctypes
import inspect
def _async_raise( tid, exctype):  # 参考stackoverflow代码,通过向线程抛异常杀死线程
    """raises the exception, performs cleanup if needed"""
    tid = ctypes.c_long(tid)  # 线程id转成c的long类型
    if not inspect.isclass(exctype):  # 检查exctype是否是一个类
        exctype = type(exctype)  # 不是类的转换为类
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))  # 用于在一个指定的线程中异步地抛出一个异常
    # 成功返回1,线程id无效返回0,其他问题返回大于1的数字
    if res == 0:
        print("ValueError(invalid thread id)")
    elif res != 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        #ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        print("PyThreadState_SetAsyncExc failed")
def stop_thread(thread):  # 终止线程
    _async_raise(thread.ident, SystemExit)  # 线程id,异常类型
6. 协程实现

对于卖票问题,就不适合用线程实现,得用协程。

生成器函数每次执行yield 返回值将返回一次返回值,并记录函数执行的位置,待下次next()的时候,会从记录的位置执行。

生成器函数return或没有yield就结束会抛异常,for捕获后会停止遍历。

python yield介绍

在这里插入图片描述

from threading import Thread  # 导入Thread类,但并未在代码中使用
from random import random  # 导入random函数,用于生成随机数
#协程允许在一个函数中暂停和恢复执行,并且可以在每个帧之间进行切换。协程是异步机制
# 模拟是否有客人来
def lai():
    return random() < 0.5  # 如果生成的随机数小于0.5,则返回True(表示有客人来)

piao = 100  # 初始化票的数量为100

# 定义一个生成器函数,用于模拟售票过程
def task(name):
    global piao  # 声明piao为全局变量
    n = 0  # 初始化售出的票数
    while piao > 0:  # 当票数大于0时,继续售票
        if lai():  # 如果有客人来
            print("{}卖出第{}张票,剩余{}张".format(name, piao, piao - 1))  # 打印售票信息,但这里有个小错误,应该是piao的当前值而不是piao-1
            piao -= 1  # 票数减1
            n += 1  # 售出的票数加1
        yield True  # 返回一个True值,表示该任务还在进行
    print(name, '卖出票数', n)  # 当票售完时,打印售出的票数
    yield False  # 返回一个False值,表示该任务已完成


# 创建一个列表,包含三个售票任务(生成器)
L = [task("李明"), task('张华'), task("王宜")]

T = True  # 初始化一个标志,用于控制外层循环
while T:  # 当T为True时,继续循环
    T = False  # 先假设所有任务都已完成
    n = len(L)  # 获取当前任务列表的长度
    for i in range(n):  # 遍历任务列表
        t = L[i]  # 取出当前任务
        if t:  # 如果任务还未完成(即t不是None)
            r = next(t)  # 执行任务的下一步(即售票或结束)
            if not r:  # 如果任务返回False,表示任务已完成
                L[i] = None  # 将任务列表中的该任务设为None
            T = T or r  # 如果任务返回True,则T保持为True或变为True
print('over')  # 所有任务都完成后,打印'over'

6. time库

print(time.ctime())# Sat Jan 20 18:10:40 2024
print(time.time())# 1705745440.5832005
 # 时间戳,从格林尼治时间1970.1.1到当前时间经过的浮点秒数
time.sleep(5) # 程序停五秒

7. os库

操作文件和目录作用
os.getcwd()获取当前工作目录的路径。
os.chdir(path)改变当前工作目录到指定的路径。
os.listdir(path)返回指定目录下的文件和目录列表。
os.mkdir(path)创建一个目录。
os.makedirs(path)递归地创建多层目录。
os.remove(path)删除一个文件。
os.rmdir(path)删除一个目录。
os.rename(src, dst)重命名文件或目录。
os.system(“chcp 65001 && cls”)执行系统命令
路径相关操作
os.path.exists(path)判断路径是否存在。
os.path.isfile(path)判断路径是否为文件。
os.path.isdir(path)判断路径是否为目录。
os.path.join(path1, path2, …)拼接多个路径组件。

8. beautifulsoup4库

pip install lxml

pip install beautifulsoup4

使用lxml作为beautifulsoup4解释器

1. 节点选择器

使用tag(标签)类对象来选择节点元素,其属性有name,attrs,string。

from bs4 import BeautifulSoup
str="""<html>
<head><title>大标题</title></head>
<body style="background-color:yellow;">
    <h2 style="background-color:red;" class="bb88" >这是一个标题</h2>
    444<p style="background-color:green;">这是一个段落。</p>666
    555<p>hello</p>
    <p>brother</p>
    <a href="https://baidu.com" class="stay" id="link1">百度</a>
</body>
</html>
"""
s=BeautifulSoup(str,'lxml')# 实例化对象
print(s.p)# 多个相同标签,只提取第一个p标签
# <p style="background-color:green;">这是一个段落。</p>
print(s.h2.name) #名称
print(s.h2.attrs)# 属性
print(s.h2.string)# 值

print(s.body.a.string) #嵌套使用
# h2
# {'style': 'background-color:red;', 'class': ['bb88']}
# 这是一个标题
# 百度
关联选择说明返回值
contents子节点列表
children迭代器
descendants子孙节点生成器
parent父节点Tag类对象(节点元素)
parents子孙节点生成器
next_sibling兄弟节点NavigableString类对象
next_siblings生成器
previous_siblingNavigableString类对象
previous_siblings生成器
s=BeautifulSoup(str,'lxml')# 实例化对象

print(s.p.contents) # ['这是一个段落。']
for i in s.p.children:
    print(i)
# 这是一个段落。
for i in s.html.descendants:
    print(i)
# 先打印<head>...</head>再打印<title>...</title>再打印 大标题

print(s.title.parent)# 父节点,title外一层的结点
    # <head><title>大标题</title></head>
for i in s.p.parents:# 获取祖先节点,包含html
    print(i)
# 先打印<body>...</body>再打印<html>...</html>

print(s.p.next_sibling)
'''
666
    555'''
for i in s.p.next_siblings:# 从666 555开始打印到<a>...</a>
    print(i)
    
print(s.p.previous_sibling)
'''

444'''
for i,j in enumerate(s.p.previous_siblings):# 枚举一下
    print(i,j)
'''
0 
    444
1 <h2 class="bb88" style="background-color:red;">这是一个标题</h2>
2 '''
2. CSS选择器

s.select()

html="""
<body>
    <div class='any'>
    <ul class='list1' id='m87'>
        <li><a href="#miao" id='a'>去找喵星人</a></li>
        <li><a href="#wang" id='b'>去找汪星人</a></li>
        <li><a href="#meng" id='c'>其他萌物</a></li>
    </ul>
    <a name="miao"></a><!--设置锚点方法1-->
	<h3 id="miao">喵星人基地</h3><!--设置锚点方法2-->
    <ul class='list2' id='c4'>
        <li>喵喵</li>
        <li>喵喵喵</li>
    </ul>
    </div>
</body>
"""
CSS选择器格式
id选择器#a
类选择器.list2
标签选择器h3
s=BeautifulSoup(html,'lxml')# 实例化对象
print(s.select(".any #c4"))
'''[<ul class="list2" id="c4">
<li>喵喵</li>
<li>喵喵喵</li>
</ul>]'''
print(s.select("ul #b"))
# [<a href="#wang" id="b">去找汪星人</a>]

# 嵌套使用
for i in s.select("ul"):
    print(i.select("li"))# i是Tag类对象
'''[<li><a href="#miao" id="a">去找喵星人</a></li>, <li><a href="#wang" id="b">去找汪星人</a></li>, <li><a href="#meng" id="c">其他萌物</a></li>]
[<li>喵喵</li>, <li>喵喵喵</li>]'''
3. 方法选择器
方法说明返回值
find_all()获取所有符合条件的元素ResultSet类
find()获取符合条件的第一个元素Tag类对象
find_parents()获取所有符合条件的祖先节点
find_parent()获取符合条件的父节点
find_next_sibling()获取后面第一个符合条件的兄弟节点
find_next_siblings()获取后面所有符合条件的兄弟节点
find_previous_sibling()获取前面第一个符合条件的兄弟节点
find_previous_siblings()获取前面所有符合条件的兄弟节点
find_all_next()获取后面所有符合条件的节点(包括子孙节点)
find_next()获取后面第一个符合条件的节点
find_all_previous()获取前面所有符合条件的节点(包括子孙节点)
find_previous()获取前面第一个符合条件的节点

find_all(self, name=None, attrs={}, recursive=True, string=None, limit=None, **kwargs)

name参数:规定了Tag类对象名字为name。可接受字符串,列表,正则,True

attrs参数:接收属性的键值对字典

kwargs参数:接收常用变量赋值的形式,如id=‘link1’,class_=‘sister’ 注意下划线

text参数:接收文本信息

limit参数:限制返回结果数量

recursive参数:决定是否获取子孙节点,默认True

print(s.find_all('span')) #查找所有的span标签,并以列表形式打印
for i in s.find_all(re.compile('^b')):# 查找所有以b开头的标签
	print(i) # i是Tag类对象
print(s.find_all(name=['a','h3'])) # 获取a标签和h3标签
print(s.find_all(name=True))# 递归地获取所有标签

9. pymysql库

db=pymysql.connect(host='localhost', user='user', password='password', port=3306)#连接数据库
cursor=db.cursor()#游标创建
sql="""SELECT * from table_name"""
cursor.execute(sql)#执行SQL
result=cursor.fetchall()#获取查询结果
db.commit() #提交到数据库执行
cursor.close()#关闭游标
db.close()#关闭连接

10. socket库

TCP/IP网络通信之Socket编程入门-哔哩哔哩

参考下面伪代码

import tkinter
import threading
import socket
import queue
import json
class Server:
    def __init__(self):
        self.thread_list=queue.Queue()#连接线程池
        pass #请自行实现
    def start_server(self):
        if self.thread_list.empty() == False:
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:  # AF_INET服务器之间的网络通信,SOCK_STREAM流式socket,使用TCP
                try:
                    s.bind((self.host, self.port))  # 服务器端函数,绑定本地端口
                    s.listen()  # 使用TCP服务器端开启监听模式,参数位可以挂起的最大连接数
                    print(f'Server is listening on {self.host}:{self.port}')
                    self.conn = s
                    conn, self.addr = s.accept()  # 接收客户端请求,返回(conn,address),
                    # conn为新的套接字对象,可以用来接收客户端数据和发送数据,address是连接客户端的地址。
                    print(f'Connected by {self.addr}')
                    while True:  # 建立连接后,持续接收客户端信息
                        data = conn.recv(8192)  # 接收TCP套接字的数据(8192字节),并以bytes形式返回,需要decode()
                        if not data:
                            break
                        data_dict = json.loads(data.decode())
                        print(data_dict.keys())
                        if (data_dict.get('a') and data_dict.get('b') and data_dict.get('c')):  # 处理客户端发来的a,b,c
                            self.a=data_dict.get('a')
                            self.b=data_dict.get('b')
                            message = json.dumps(
                                {"a": str(self.a), "b": str(self.b)}).encode()
                            # 转json格式
                            conn.sendall(message)
                            #self.refresh()
                            # 这里刷新gui界面
                except ConnectionResetError as e:
                    print("客户端连接关闭")
                    self.stop_connect()#关闭连接函数
                except ConnectionAbortedError as e:
                    print("你的主机中的软件中止了一个已建立的连接。")
                    self.stop_connect()
    def stop_connect(self):
        while self.thread_list.empty() == False:
            #服务器端没法停止监听,只能杀线程
            self.conn=0
            t = self.thread_list.get_nowait()
            self.create_gui()
            stop_thread(t)#需要使用ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
import json
import tkinter
import threading
import socket
import queue
class Client:
    def __init__(self):
        pass
    def start_client(self):
        try:
            if self.thread_list.empty()==False:
                with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: #AF_INET服务器之间的网络通信,SOCK_STREAM流式socket,使用TCP
                    s.connect((self.host, self.port)) #客户端用来连接服务器端函数,连接本地的端口
                    self.refresh()#刷新gui界面
                    self.conn=s#保存连接对象
                    self.addr=s.getsockname()#获取客户端地址和端口号
                    message_1 = json.dumps({'a':str(self.a),'b':str(self.b),'c':str(self.c)}).encode()#转为json格式字符串
                    s.sendall(message_1)#完整发送TCP数据,成功返回None,失败则抛出异常

                    # 持续接收服务器响应
                    while True:
                        data = s.recv(8192)#recv接收TCP套接字的数据(8192字节),并以bytes形式返回,需要decode()
                        if not data:  # 如果recv返回空字节串,说明服务器已经关闭连接
                            break
                        data_dict = json.loads(data.decode())
                        if data_dict['a'] and data_dict['b']: 
                            message_2=json.dumps({"result":"你说得对"}).encode()
                            s.sendall(message_2)
                            self.refresh()
            else:
                print("已建立一条连接!")
        except ConnectionResetError as e:
            print("客户端连接关闭")
            self.stop_connect()
        except ConnectionAbortedError as e:
            print("你的主机中的软件中止了一个已建立的连接。")
            self.stop_connect()
        except ConnectionRefusedError as e:
            print("由于目标计算机积极拒绝,无法连接。")
            self.stop_connect()
    def stop_connect(self):
        if self.thread_list.empty()==False:
            try:
                t = self.thread_list.get_nowait()#下一个可能因为线程已自动退出而抛异常,所以线程先出队列
                self.conn.close()#连接终止,使线程退出
                self.refresh()
            except AttributeError as e:
                print("线程已自动终止")
                self.refresh()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值