python修炼——协程and正则表达式!
协程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 的内容,共同进步。
阅读更多
- 利用python正则表达式 遍历目录后取出目录树中的所有特定目录
- Python正则表达式指南
- python 正则表达式 \b 大坑
- Python:入门到实现网络爬虫 Day4 --正则表达式
- Python爬虫实例(4)-用urllib、re和正则表达式爬取网页图片
- python IP的正则表达式
- Python正则表达式的七个使用范例详解
- Python_Day6_反射_正则表达式之篇
- python正则表达式小mark
- 高级正则表达式技术(Python版)
- Python 正则表达式
- [整理] python的正则表达式re模块的常用方法
- Python正则表达式实现截取成对括号的方法
- python - re (正则表达式的学习)
- python学习:python中的正则表达式函数match和search()的区别
- Python基础篇【第3篇】: Python正则表达式
- Python中正则表达式
- 基于python的正则表达式学习笔记
- python 学习记录(2)—re 正则表达式模块的使用
- Python网络爬虫(3)正则表达式