模块和包-初识模块和包 什么是模块和包?
包的安装 通过pip安装 在python的目录中,pip.exe是一个专门用于帮助下载第三方包的工具。
1 2 3 4 5 6 7 D:\Python -python.exe python解释器 -Scripts -pip.exe 包管理工具 -Lib(内置+第三方) -site-packages -第三方包
pip的常见命令
下载配置 https://pypi.org/是一个开源包的获取网站,pip.exe通过这个网站将包下载到本地,但有时速度比较慢。
可以通过国内的其他同步网站下载,比如豆瓣,基于豆瓣源去下载第三方包:
一次性操作:
1 pip3 install 包名 -i https://pypi.douban.com/simple/
永久使用豆瓣
1 2 pip config set global .index-url https://pypi.douban.com/simple/
源码安装 如果pip.exe中下载不到想要的包,可以通过源码安装
下载源码并解压
安装[在终端操作]
进入源码目录
执行安装命令
1 2 python3.9 setup.py build python3.9 setup.py install
wheel安装 有些源码开发者会把源码打包成wheel包,以供下载和安装。
pip支持wheel安装
下载wheel包
进入终端安装
模块和包-模块和包的导入 模块和包的导入路径
python内置的模块都放在了python的安装目录下,可以直接导入使用
一般情况下,自定义的模块和包需要放在运行文件的同级目录下,才可以导入使用
1 2 3 import 模块名 import 包名.模块名
当需要让python去自定义的目录中寻找模块时,要用到sys
模块:sys.path
是获取python寻找模块的目录
1 2 3 4 import syssys.path.append(r"模块所在目录" ) import 模块名
自定义模块不能与python内置模块重名
模块和包的导入方式 import导入 导入级别:导入py
文件
from导入 导入级别:可以是py
文件中的函数,也可以是py
文件,更为灵活,比如:
1 2 3 4 5 from 包名 import 模块名 from 模块名 import func1 from 模块民 import func1,func2,func3 from 模块名 import * from 模块名 import func1 as f1
一般来说,单层目录时,可以用import
或from
导入,当层级较深时,用from
导入
主文件 主文件是指一个python项目中,作为程序入口的py
文件。
py
文件执行时,系统内部会创建一个变量名,__name__
主动执行时,__name__="__main__"
,被导入执行时,__name__=py文件名
所以当编写主文件时,运行代码前要加上if __name__="__main__":
,防止别人导入时执行
模块和包-内置模块 内置模块是python中提供好的功能模块
hashlib 对数据进行加密的模块
比如开发项目时,密码不能用明文存储,防止数据库泄露时密码也泄露,就要用到hashlib
模块
1 2 3 4 5 6 7 8 import hashlibname = "邓胖胖" pwd = "123456" obj = hashlib.md5() obj.update(pwd.encode("utf-8" )) res = obj.hexdigest() print (res)
random 帮助我们生成一些随机数据,比如:
1 2 3 4 import randomv1 = random.randint(1 , 10 ) v2 = random.uniform(1 , 10 )
1 2 3 4 5 6 import randomdata_list = [11 ,22 ,33 ,44 ,55 ] v3 = random.choice(data_list) v4_list = random.sample(data_list,3 ) print (v4_list)
1 2 3 4 5 import randomdata_list = [i for i in range (10 )] random.shuffle(data_list) print (data_list)
json 本质上是一种数据格式,以字符串的形式存在。作用是在不同的编程语言之间实现数据传输。
json
格式外部整体是一个大的字符串,
json
格式内部的字符串一定要用双引号
json
格式不存在元组的数据类型,转换过程中会将元组转换为列表
json
格式中一般只包括:整数、小数、字符串、双引号、字典、列表、true
/false
、null
序列化
1 2 3 4 5 6 7 import jsoninfo = {"k1" :123 , "k2" :(2 ,3 ,4 ,5 )} res = json.dumps(info) print (res)
反序列化
1 2 3 4 5 6 7 import jsondata_string = '{"k1": 123, "k2": [2, 3, 4, 5]}' res = json.loads(data_string) print (res)
time
获取当前的时间戳
1 2 3 import timev1 = time.time()
程序停止N秒,再继续运行
1 2 3 4 5 import timewhile True : print ("上岸" ) time.sleep(1 )
datetime
获取当前时间
1 2 3 4 import datetimev1 = datetime.datetime.now()
datetime
类型转换为字符串类型
1 2 3 4 from datetime import datetimev1 = datetime.now() v2 = v1.strftime("%Y-%m-%d %H:%M:%S" )
字符串类型转换为datetime
类型
1 2 3 4 from datetime import datetimev1 = "2023-02-14" v2 = datetime.strptime(v1, "%Y-%m-%d" )
datetime
类型转换为时间戳类型
1 2 3 4 from datetime import datetimev1 = datetime.now() v2 = v1.timestamp()
时间戳类型转换为datetime
类型
1 2 3 4 5 from datetime import datetimeimport timev1 = time.time() v2 = datetime.fromtimestamp(v1)
datetime
数据类型存在的意义
1 2 3 4 5 6 7 from datetime import datetime,timedeltav1 = datetime.now() v2 = v1 - timedelta(days=200 ) v3 = v1 + timedelta(days=29 ,hours=34 ,minutes=23 ,seconds=122 )
os
路径的拼接
1 2 3 windows: C:\xx\xx\xxxx Mac: /user/xx/xx/xxxx Linux: /user/xx/xx/xxxx
1 2 3 4 import ospath = os.path.join("x1" ,"x2" ,"x3" ,'log.txt' ) print (path)
找到当前目录的上级目录
1 2 3 import ospath = "x1/x2/x3/log.txt" file_path = os.path.dirname(file_path)
绝对路径
绝对路径是从根目录开始的路径
相对路径是基于当前文件所在目录的路径
1 2 3 4 import osfile_name = "xx" file_path = os.path.abspath(file_name)
判断文件是否存在
1 2 3 4 5 6 7 8 import osfile_path = os.path.join("xx" ,"xx.txt" ) os.path.exists(file_path)
创建文件夹
1 2 3 4 5 import ospath = os.path.join("xx" ,"xx" ,"xxxx" ) if not os.path.exist(path): os.makedirs(path)
删除文件
1 2 3 4 5 import ospath = os.path.join("xx" ,"xx" ,"xxxx" ) os.remove(path)
判断一个目录是否是文件夹
1 2 3 4 import ospath = os.path.join("xx" ,"xx" ,"xxxx" ) os.path.isdir(path)
查看某个目录下的文件和文件夹(单级)
1 2 3 4 import osres = os.listdir("D:\connect\Assets" ) print (res)
查看某个目录下的所有文件和文件夹(多级)
1 2 3 4 5 6 7 import osfor item in os.walk("D:\connect\Assets" ): print (item)
1 2 3 4 5 6 7 import osfor in_path, folder_list, file_list in os.walk("D:\connect\Assets" ): for file in file_list: abs_path = os.path.join(in_path,file) print (abs_path)
shutil
删除文件夹
1 2 3 4 5 import osimport shutil path = os.path.join("xx" ,"xx" ,"xxxx" ) shutil.rmtree(path)
拷贝文件夹
1 2 3 import shutilshutil.copytree("原文件夹路径" , "目标文件夹路径" )
拷贝文件(两种方式)
1 2 3 4 5 6 7 import shutilshutil.copy("原文件夹路径" , "目标文件夹路径\\" ) shutil.copy("原文件夹路径" , "目标文件夹路径文件名" )
重命名文件或文件夹
1 2 3 import shutilshutil.move("原文件路径文件(夹)名" , "目标文件路径文件(夹)名" )
压缩和解压缩
1 2 3 4 5 6 7 8 9 import shutil""" base_name 压缩后,压缩包的名称 root_dir 要压缩的文件夹的路径 format 后缀名 """ shutil.make_archive(root_dir = "xxx" , base_name = "xx/xxx" ,format = "zip" )
1 2 3 4 5 6 7 8 9 import shutil""" filename 压缩包的文件名 extract_dir 解压后,文件的路径 format 后缀名 """ shutil.unpack_archive(filename="dd.zip" , extract_dir="xx/xxx" , format ="zip" )
模块和包-正则表达式和re模块 正则表达式 正则表达式,是用语句来描述一些字符串的特征,可以与re
模块结合,将字符串提取出来。比如:
1 2 3 4 import retext = "sdhkfsgk23874823skjfsbj34563hsdj" data_list = re.findall("正则表达式" , text)
字符相关
数量相关
*
代表0或多个
+
代表1或多个
?
代表0或1个
{n}
代表固定n
个
{n,}
代表n
个及以上
{n,m}
代表大于等于n
,小于等于m
个
注意:默认贪婪匹配,非贪婪匹配需要在数量后加?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 re.findall("d\d+" , text) re.findall("d\d*" , text) re.findall("d\d?" , text) re.findall("d\d{3}" , text) re.findall("d\d{5,}" , text) re.findall("d\d{5,6}" , text) text = "aabbccccaaadddd" res = re.findall("a+" , text)
分组
提取部分区域的数据
1 2 3 4 5 6 7 8 9 import retext = "手机号17633554278中国联通" data_list = re.findall("1\d{6}(\d{4})" ,text) data_list = re.findall("((1\d{2})\d{4}(\d{4}))" ,text)
“或”的关系
1 2 3 4 5 import retext = "手机号17633554278和手机号17633554273都是我名下的,后面那个送人了" data_list = re.import ("1\d{6}427(8|3)" ,text)
限制开头和结尾
1 2 3 4 5 import retext = input ("请输入手机号:" ) res = re.match ("^1[3-9]\d{9}$" , text)
应用
企鹅号
手机号
身份证号
邮箱
1 2 3 4 5 6 7 8 9 10 11 12 """ 一般邮箱格式:xxx@xxx.com 正则表达式出现的 . 代表的是除换行符外的一个任意字符,当需要表示字符 . 时,用 \. """ import retext = "我的126邮箱是dengjinjun0805@126.com,QQ邮箱是498790885@qq.com" data_list = re.findall("\w+@\w+\.com" , text, re.ASCII) print (data_list) data_list = re.findall("[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+" ,text)
re模块
获取所有匹配成功的结果
1 re.findall("正则表达式" , "文本" )
从字符串开头进行匹配,返回第一个对象
使用re.match()
对字符串开头第一个字符开始匹配,如果开头不匹配不会继续寻找。
1 2 3 4 5 6 7 8 9 import retext = "changzhou university" res = re.match ("u\w+y" , text) res = re.match ("c\w+\s" , text) if res: content = res.group()
从整个字符串进行匹配,返回第一个对象
使用re.search()
对整个字符串进行匹配,返回第一个对象,与re.match()
不同的是,开头不匹配,仍然会继续寻找,找到后返回一个对象,通过group()
方法获取,否则返回None
1 2 3 4 5 6 import retext = "changzhou university" res = re.search("u\w+y" , text) if res: content = res.group()
字符串的分割
使用re.split()
对字符串进行分割,一般的字符串分割只能按照一个字符进行分割,而利用正则表达式,可以实现按照不同的字符进行分割,比如:
1 2 3 4 import retext = "23+34-5" data_lsit = re.split("[+-]" , text)
模块和包-第三方模块 request模块 request
模块是一个重要的第三方模块,可以让我们通过代码向某些地址发送网络请求,然后我们就可以获取到结果。
抓包
查看网络请求,空白处右键——检查——网络
查看地址:url
请求的方式
传递的数据:response
通过代码伪造浏览器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import requestres = request.get( url = "xxxx" headers = { "User-Agent" :"xxxx" } ) res.encoding = "utf-8" print (res.text)res.content.decode("utf-8" ) print (json.loads(res.text))
BeautifulSoup4模块 BeautifulSoup4
模块专门用于帮助我们在HTML格式的字符串中提取我们想要的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from bs4 import BeautifulSoupdata = """<meta charset="utf-8"/> <meta content="webkit" name="renderer"> <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"/> <meta content="width=1400" name="viewport"> <title>常州大学</title> <meta content="常州大学" name="keywords"/> <meta content="常州大学" name="description"/>""" soup_object = BeautifulSoup(data,"html.parser" ) soup_object.find(name = "xxx" ,attrs = {"id" : "xxx" ,"class" : "xxx" }) soup_object.find_all(name = "xxx" ,attrs = {"id" : "xxx" ,"class" : "xxx" }) res.text res.attrs["src" ] res.attrs["name" ]
一个抓取联通网上商城商品信息的案例 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 import requestsfrom bs4 import BeautifulSoup as bsimport reimport osFILE_PATH = "picture" def download (url, file_path ): pic = requests.get(url=url) if pic: with open (file_path, mode="wb" ) as f: f.write(pic.content) def run (): if not os.path.exists(FILE_PATH): os.makedirs(FILE_PATH) res = requests.get( url="http://s.10010.com/hebei/mobilelist-0-0-0-0-0-0-0-0-29-0-0-p2/" ) data = res.content.decode("utf-8" ) soup_object = bs(data, "html.parser" ) goods_object_list = soup_object.find_all(name="li" , attrs={"class" : "goodsLi" }) for item in goods_object_list: name_object = item.find(name="p" , attrs={"class" : "mobileGoodsName" }).find(name="a" ).text.strip() price_object = item.find(name="p" , attrs={"class" : "evaluation" }).text.strip() price = re.findall("¥(\d+)" , price_object)[0 ] comment_object = item.find(name="p" , attrs={"class" : "evalNum" }).find(name="a" ).text.strip() comment = re.findall("已有(\d+人)评价" , comment_object)[0 ] img_url = item.find(name="img" ).attrs["data-original" ] file_name = "{}.jpg" .format (img_url[-18 :-1 ]) file_path = os.path.join(FILE_PATH, file_name) download(img_url, file_path) line = "{}|{}|{}|{}|{}\n" .format (name_object, int (price), comment, img_url, file_path) with open ("db.txt" , mode="a" , encoding="utf-8" ) as f: f.write(line) if __name__ == "__main__" : run()