您的位置:首页 > 编程语言 > Python开发

python修炼——协程and正则表达式!

2018-08-19 18:43 127 查看

协程and正则

昨日回顾

迭代器

iter next

生成器

yield 关键字 代码执行到 yield 就会停止

next 进行解阻塞

列表推导式: a = [x for x in range(10)]

生成器表达式:把列表推导式的 [] 改成 ()

生成器函数:加了 yield 的函数

今日内容

gevent 库

踩的坑:python3.7 版本对这个库不太友好,重新换成 python 3.6.4 的32位版本。

gevent 是对 greenlet 库进行封装,greenlet 是对 yield 关键字进行封装

gevent.sleep() 在协程等待的时候,先去执行下一个任务以此来实现多任务

from gevent import monkey

monkey.patch_all() # monkey 可以把代码中所有的延时换成 gevent

gevent.joinall([]) 推荐这种方式

"""
简单的爬虫,使用协程并发来下载两张斗鱼图片
"""

import urllib.request
import gevent
from gevent import monkey

monkey.patch_all()

def downloader(img_name, img_url):
req = urllib.request.urlopen(img_url)

img_content = req.read()

with open(img_name, "wb") as f:
f.write(img_content)

def main():
gevent.joinall([
gevent.spawn(downloader, "3.jpg",
"https://rpic.douyucdn.cn/appCovers/2017/09/22/1760931_20170922133718_big.jpg"),
gevent.spawn(downloader, "4.jpg",
"https://rpic.douyucdn.cn/appCovers/2017/09/17/2308890_20170917232900_big.jpg")
])

if __name__ == '__main__':
main()
协程

协程依赖于线程,线程依赖于进程。进程消耗资源最大,线程其次,协程最小,

正则

import re

ret = re.match(正则表达式,要匹配的数据)

ret.group() # 提取匹配出来的数据

正则表达式

匹配单个字符

​ . 匹配任意一个字符,除了 \n

​ \d 匹配 0-9 的数字

​ \D 匹配非数字 与\d 相反

​ [] 匹配 [] 中列举的字符

​ \w 匹配 0-9 a-z A-Z _ 慎用,可以匹配中文

​ \W 匹配非 \w

​ \s 匹配空白,即空格、tab键, \t 表示 tab 键

​ \S 匹配非空 与\s 相反

匹配多个字符

​ {m,n} 匹配前一个字符 m-n 次

​ {m} 匹配前一个字符 m 次

​ ? 匹配前一个字符1次或0次,可有可无 # python 默认贪婪,加 ?变为非贪婪

​ * 匹配前一个字符0次或任意次,不匹配\n 可以使用模块中的 re.S 模块来忽略\n

​ + 匹配枪一个字符 1次或任意次

开头结尾

​ ^ 匹配字符串开头 # [^>] 在 [] 中 ^ 表示非

​ $ 匹配字符串结尾

匹配分组

​ | 匹配左边或者右边,表示 或

​ (ab) 将括号中的字符作为一个分组

​ \num 引用分组num匹配到的字符串

​ (?p\) 给分组起别名

​ (?p=name) 引用别名为name的分组取到的字符串

re模块高级用法

​ re.match() 能够匹配出以xxx开头的字符串

​ re.search() 能够匹配出包含xxx的字符串

​ re.findall() 能够找出所有xxx字符串

​ re.sub() 将匹配到的数据进行替换

​ re.split() 根据匹配进行切割字符串,并返回一个列表

Python里数量词默认是贪婪的

​ 贪婪:总是尝试匹配尽可能多的字符

​ 非贪婪:总是尝试匹配尽可能少的字符。

​ 在”“,”?”,”+”,”{m,n}”后面加上 ? , 使贪婪变成非贪婪。

r的作用

python中字符串加上 r 表示原生字符串,不需要频繁转义

练习代码

import re

"""判断变量名是否符合要求"""
# 一些变量名
names = ["age", "_age", "1age", "age1", "a_age", "age_1_", "age!", "a#123", "__________"]

for name in names:
# 使用正则来判断是否符合要求
# 只能由字母、数字、下划线组成,不能以数字开头
# 正则以 ^ 开头, $ 结尾
ret = re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", name)

# 判断是否有数据
if ret:
print("%s 变量名符合要求,正则匹配的数据是 %s" % (name, ret.group()))

else:
print("%s 不符合要求" % name)
import re

def email_1():
"""
匹配网易邮箱
qinyifan__123@163.com
命名规范:由 0-9 a-z A-Z _ 组成,不能以数字开头
"""
# 提示输入邮箱
email_str = input("请输入你的邮箱:")

# 正则判断邮箱是否正确
ret = re.match(r"^[a-zA-Z_][0-9a-zA-Z_]{3,19}@163\.com", email_str)

if ret:
print("邮箱 %s 名字合法" % email_str)
else:
print("邮箱 %s 名字不合法" % email_str)

def email_2():
"""
匹配任意邮箱
:return:
"""
# 提示输入邮箱
email_str = input("请输入你的邮箱:")

# 正则判断邮箱是否正确
# ret = re.match(r"^[0-9a-zA-Z_]*@[0-9a-z]{3,5}\.(com|com\.cn|net|org\.cn\.com)", email_str)
ret = re.match(r"^[0-9a-zA-Z_]+@[0-9a-zA-Z]+(\.[a-zA-Z])", email_str)
if ret:
print("邮箱 %s 名字合法" % email_str)
else:
print("邮箱 %s 名字不合法" % email_str)

def phone_1():
"""
匹配座机号码
要求:区号3-4位,号码7-8位,号码和区号之间可有有-号,可以没有
:return:
"""
# 提示输入手机号
phone_num = str(input("请输入你的手机号:"))

# 正则判断
ret = re.match(r"^[\d]{3,4}-?[\d]{7,8}$", phone_num)

if ret:
print("手机号 %s 正确" % phone_num)
else:
print("手机号 %s 不正确" % phone_num)

def phone_2():
"""
匹配尾号不是4和7的手机号
:return:
"""
# 提示输入手机号
phone_num = str(input("请输入你的手机号:"))

# 正则判断
ret = re.match(r"^[0-35-68-9]{11}$", phone_num)

if ret:
print("手机号 %s 正确" % phone_num)
else:
print("手机号 %s 不正确" % phone_num)

def main():
email_1()
email_2()
phone_1()
phone_2()

if __name__ == '__main__':
main()
"""
使用正则判断来爬取一整个网页的图片,简单的爬虫
思路:
1.先打开要爬取的网页,找到网页源代码,保存在 douyu.txt 文件中,
2.进行文件打开操作,使用正则判断得到每个图片地址并且保存在一个列表中
3.遍历得到每个图片地址,使用urllib库取得每个图片的信息,指定路径进行写入操作。
"""

import re
import urllib.request
import gevent
from gevent import monkey
import time

monkey.patch_all()

"""

封装函数
实现一下多任务  失败
"""

def find_img_url():
"""打开存储网页源代码的文件,使用正则得到图片网址列表"""
with open("douyu.txt", "rb") as f:
file = f.read().decode("utf-8")
# print(file)
ret = re.findall(r"https://.*\.jpg", file)
print(ret)

return ret

def download_img(ret):
"""对得到的网址列表进行操作"""
num = 0
for img_url in ret:
num += 1
content = urllib.request.urlopen(img_url)
img = content.read()
with open("./douyu_img/img" + str(num) + ".jpg", "wb") as f:
f.write(img)
print("第 %d 张下载完毕" % num)

print("全部下载完毕")

def main():

# 先调用获取网址列表的函数
ret = find_img_url()

# download_img(ret)

# 创建协程
# g = gevent.spawn(download_img, ret)
# g.join()

gevent.joinall([
gevent.spawn(download_img, ret)
])

if __name__ == '__main__':
main()

用了好久的 CSDN ,第一次在这上面发布文章,之前一直发布在微信公众号上,有兴趣可以搜索 QYFabc 或者扫描下方的二维码来关注我的公众号。我会每天发布自己学习 python 的内容,共同进步。

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: