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():
    """
    匹配网易邮箱
    [email protected]
    命名规范:由 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学习公众号二维码

猜你喜欢

转载自blog.csdn.net/qyf__123/article/details/81840386
今日推荐