<supermarket name="永辉超市" address="肖家河大厦">
<staffs>
<staff id="s001" class="c1">
<name>小明name>
<position>收营员position>
<salary>4000salary>
staff>
<staff id="s002">
<name>小花name>
<position>促销员position>
<salary>3500salary>
staff>
<staff id="s003">
<name>张三name>
<position>保洁position>
<salary>3000salary>
staff>
<staff id="s004" class="c1">
<name>李四name>
<position>收营员position>
<salary>4000salary>
staff>
<staff id="s005">
<name>王五name>
<position>售货员position>
<salary>3800salary>
staff>
staffs>
<goodsList>
<goods discount="0.9">
<name>泡面name>
<price>3.5price>
<count>120count>
goods>
<goods class="c1">
<name>火腿肠name>
<price>1.5price>
<count>332count>
goods>
<goods>
<name>矿泉水name>
<price>2price>
<count>549count>
goods>
<goods discount="8.5">
<name>面包name>
<price>5.5price>
<count>29count>
goods>
goodsList>
supermarket>
etree.XML(xml数据)etree.HTML(html数据)from lxml import etree
with open('../file/data.xml', encoding='utf-8') as f:
root = etree.XML(f.read())
根据xpath获取指定标签
节点对象.xpath(路径) - 返回路径对应的所有的标签,返回值是列表,列表中的元素是标签对象(节点对象)
路径的写法:
注意:绝对路径和全路径的写法以及查找方式和是用谁去点的xpath无关
# 绝对路径
result = root.xpath('/supermarket/staffs/staff/name/text()')
print(result)
# 相对路径
result = root.xpath('./staffs/staff/name/text()')
print(result)
staff1 = root.xpath('./staffs/staff')[0] # 获取第一个员工对应的staff标签
result = staff1.xpath('./name/text()')
print(result)
result = staff1.xpath('../staff/name/text()')
print(result)
# 全(任意)路径
result = root.xpath('//name/text()')
print(result)
result = staff1.xpath('//goods/name/text()')
print(result)
# 运行结果
'''
['小明', '小花', '张三', '李四', '王五']
['小明', '小花', '张三', '李四', '王五']
['小明']
['小明', '小花', '张三', '李四', '王五']
['小明', '小花', '张三', '李四', '王五', '泡面', '火腿肠', '矿泉水', '面包']
['泡面', '火腿肠', '矿泉水', '面包']
'''
节点对象.xpath(获取标签的路径/text()) - 获取指定路径下所有标签的标签内容result = root.xpath('//position/text()')
print(result)
# 运行结果
'''
['收营员', '促销员', '保洁', '收营员', '售货员']
'''
节点对象.xpath(获取标签的路径/@属性名)result = root.xpath('/supermarket/@name')
print(result)
result = root.xpath('//staff/@id')
print(result)
# 运行结果
'''
['永辉超市']
['s001', 's002', 's003', 's004', 's005']
'''
# 1) 位置相关谓语
# [m] - 第m个
result = root.xpath('//staff[1]/name/text()')
print(result)
# [last()] - 最后第一个
# [last()-m] - 第n-m个/倒数第m+1个
# [position()m]、[position()<=m]、[position()>=m]
# 前m-1个、后n-m个、前m个、后n-m+1个
# 2) 属性相关谓语
# [@属性名=属性值] - 获取指定属性是指定值的标签
result = root.xpath('//staff[@class="c1"]/name/text()')
print(result)
# [@属性名]
result = root.xpath('//goods[@discount]/name/text()')
print(result)
# 3) 子标签内容相关谓语 - 根据子标签的内容来筛选标签
# [子标签<数据]、[子标签>数据]、[子标签<=数据]、[子标签>=数据]、[子标签=数据]
result = root.xpath('//goods[price=2]/name/text()')
print(result)
# 运行结果
'''
['小明']
['小明', '李四']
['泡面', '面包']
['矿泉水']
'''
# 写路径的时候,用*来表示任意标签或任意属性
result = root.xpath('//staff[1]/*/text()')
print(result)
result = root.xpath('//*[@class="c1"]/name/text()')
print(result)
result = root.xpath('//goods[@*]/name/text()')
print(result)
# 运行结果
'''
['小明', '收营员', '4000']
['小明', '李四', '火腿肠']
['泡面', '火腿肠', '面包']
'''
# 路径1|路径2|。。。 - 获取所有路径的内容
result = root.xpath('//goods/name/text()|//staff/position/text()')
print(result)
# 运行结果
'''
['收营员', '促销员', '保洁', '收营员', '售货员', '泡面', '火腿肠', '矿泉水', '面包']
'''
进程和线程
进程就是车间,线程就是车间里面的工人。
一个进程中默认有一个线程,这个线程叫主线程。
线程的特点
如果在一个线程中执行多个任务,任务是串行执行的。
(当一个程序中有很多个任务的时候,如果只有一个线程,那么程序的执行效率会很低)
多线程
一个进程中有多个线程就是多线程。
多线程执行任务的时候,多个任务可以同时(并行)执行。
多线程原理
一个cpu同一时间只能调度一个线程,多线程其实是cpu快速的在多个线程之间进行切换,造成多个线程同时执行的假象。
(提高cpu利用率)
from threading import Thread
from time import sleep
from datetime import datetime
def download(name):
print(f'{name}开始下载:{datetime.now()}')
sleep(2)
print(f'{name}下载结束:{datetime.now()}')
def main():
# 1)创建线程对象
"""
线程对象 = Thread(target=函数, args=元组)
a.函数 - 可以是普通函数函数名,也可以是匿名函数。这个函数就是需要子线程中执行的任务。
b.元组 - 元组中的元素就是在子线程中调用target对应的函数的时候需要的参数
"""
time1 = datetime.now()
t1 = Thread(target=download, args=('肖生克救赎',))
t2 = Thread(target=download, args=('霸王别姬',))
t3 = Thread(target=download, args=('阿甘正传',))
# 2)启动线程 - 让子线程调用对应的函数
t1.start()
t2.start()
t3.start()
time2 = datetime.now()
print(time2-time1)
if __name__ == '__main__':
main()
# 运行结果
'''
肖生克救赎开始下载:2022-08-20 10:05:23.121123
霸王别姬开始下载:2022-08-20 10:05:23.125239
阿甘正传开始下载:2022-08-20 10:05:23.126225
0:00:00.006098
肖生克救赎下载结束:2022-08-20 10:05:25.137502阿甘正传下载结束:2022-08-20 10:05:25.137502 霸王别姬下载结束:2022-08-20 10:05:25.137502
'''
# 在main()中加入线程阻塞
def main():
time1 = datetime.now()
t1 = Thread(target=download, args=('肖生克救赎',))
t2 = Thread(target=download, args=('霸王别姬',))
t3 = Thread(target=download, args=('阿甘正传',))
t1.start()
t2.start()
t3.start()
# 3) 加入线程阻塞
t1.join()
t2.join()
t3.join()
time2 = datetime.now()
print(time2-time1)
# 运行结果
'''
肖生克救赎开始下载:2022-08-20 10:11:27.210833
霸王别姬开始下载:2022-08-20 10:11:27.213781
阿甘正传开始下载:2022-08-20 10:11:27.213781
霸王别姬下载结束:2022-08-20 10:11:29.214501
肖生克救赎下载结束:2022-08-20 10:11:29.222479
阿甘正传下载结束:2022-08-20 10:11:29.229458
0:00:02.019667
'''
submit()
一次添加一个任务:submit(函数, 实参1, , 实参2, 实参3, ...)
注意:实参的数量由前面的函数在调用的时候需要的实参来决定
map()
同时添加多个任务: map(函数, 参数对应的序列)
注意:使用map添加多个任务的时候,任务对应的函数必须是有且只有一个参数的函数
关闭线程池
线程池关闭后无法再添加新的任务,并且会阻塞当前线程等待整个线程池的任务都完成
shutdown()
from time import sleep
from datetime import datetime
from random import randint
from concurrent.futures import ThreadPoolExecutor
def download(name):
print(f'{name}开始下载:{datetime.now()}')
sleep(randint(2, 7))
print(f'{name}下载结束:{datetime.now()}')
def main():
# 使用线程池下载1000个电影
# ThreadPoolExecutor(线程数最大值)
pool = ThreadPoolExecutor(3)
pool.submit(download, '肖生克的救赎')
pool.submit(download, '霸王别姬')
pool.map(download, ['V字仇杀队', '恐怖游轮', '沉默的羔羊'])
pool.shutdown()
print('==============完成!=============')
if __name__ == '__main__':
main()
# 运行结果
'''
肖生克的救赎开始下载:2022-08-20 10:22:28.727568
霸王别姬开始下载:2022-08-20 10:22:28.735995
V字仇杀队开始下载:2022-08-20 10:22:28.736993
肖生克的救赎下载结束:2022-08-20 10:22:30.738571
恐怖游轮开始下载:2022-08-20 10:22:30.738571
霸王别姬下载结束:2022-08-20 10:22:32.747770
沉默的羔羊开始下载:2022-08-20 10:22:32.754632
V字仇杀队下载结束:2022-08-20 10:22:33.741739
恐怖游轮下载结束:2022-08-20 10:22:34.747225
沉默的羔羊下载结束:2022-08-20 10:22:35.759421
==============完成!=============
'''
通过with操作来自动关闭多线程
def main():
# 使用线程池下载1000个电影
# ThreadPoolExecutor(线程数最大值)
movies = ['肖生克的救赎', '霸王别姬', 'V字仇杀队', '恐怖游轮', '沉默的羔羊']
with ThreadPoolExecutor(max_workers=3) as pool:
for i in movies:
pool.submit(download, i)
print('==============完成!=============')
常见的指令操作
执行指令的工具: Windows - 命令提示符(cmd) 、Mac - 终端
# win
python py文件路径
# mac:
python3 py文件路径
# 注意:如果是windows操作系统,cd操作如果要跨盘需要先切盘,然后再cd
# 切盘方法:
D:
cd 文件夹相对路径、文件夹绝对路径
# win:
dir
# Mac:
ls
用指令创建虚拟环境
第一步:找到一个用来放虚拟环境的文件夹
第二步:通过cd指令进入到存放虚拟环境的文件夹中
第三步:创建虚拟环境
python -m venv 虚拟环境名
python3 -m venv 虚拟环境名
(mac) source 虚拟环境目录/bin/activate
(windows) 虚拟环境目录\Scripts\activate.bat
cmd要写绝对路径,否则会报错,power shell可以写相对路径
deactivate
常用pip指令(pip - Python包管理工具)
pip list - 查看当前环境已经安装过的所有的第三方库
pip install 第三方库名称 - 下载并且安装指定的第三方库
pip install 第三方库名称 -i 镜像地址 - 在指定的镜像地址中下载安装
pip install 第三方库名称==版本号 -i 镜像地址
pip install 第三方库名称1 第三方库名称2
pip freeze > 依赖文件名 - 生成依赖文件
pip install -r 依赖文件路径 - 批量安装
pip uninstall 第三方库名称 - 卸载指定的第三方库