16_python笔记-正则爬虫-高阶函数


博客cpen_web

练习1

1、电子邮箱验证(username@domain-inc.com)

·username长度6-18之间,则字母、数字、下划线组成
·domain-inc由字母、数字、中划线组成

示例

import re
msg = input("请输入email:")
if re.findall(r"^\w{6,18}@[A-Za-z0-9\-]+\.com$", msg):
    print("yes")
else:
    print("no")

2、从左往右依次匹配

示例

import re
msg = 'san chuang tong le, huan ying ni "hello world", learn python'
ret = re.findall(r'\w+|"[\w ]+', msg)   # 注:不是零宽断言  匹配到引号
print(ret)
#结果为 ['san', 'chuang', 'tong', 'le', 'huan', 'ying', 'ni', '"hello world', 'learn', 'python']
ret = re.findall(r'\w+|(?<=")(?:[\w ]+)(?=")', msg)     # 注:这种写法 先匹配\w+
print(ret)
#结果为 ['san', 'chuang', 'tong', 'le', 'huan', 'ying', 'ni', 'hello', 'world', 'learn', 'python']
ret = re.findall(r'(?<=\")(?:[\w ]+)(?=")|\w+', msg)    # 注:匹配到引号时发现 前面没引号 后面也没有引号
print(ret)             # 注:解决问题了  因为断言先行 每次匹配先匹配零宽断言的;引号不占用匹配宽度,仅仅只是占有位置
#结果为 ['san', 'chuang', 'tong', 'le', 'huan', 'ying', 'ni', 'hello world', 'learn', 'python']

3、抓取任意站点,将所有的图片下载到本地

豆瓣电影首页的图片()
前置知识:urllib或requests模块

示例1:curl命令

[root@sanchuang-linux ~]# curl "https://movie.douban.com/"		# 注:curl命令模拟请求
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
……………………………
<html lang="zh-CN" class="">…………………………
</title>
[root@sanchuang-linux ~]# curl "https://movie.douban.com/" &> /tmp/douban	#注:将内容写入文件
[root@sanchuang-linux ~]# less /tmp/douban 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
……………………………
<html lang="zh-CN" class="">…………………………
</title>

示例2:对称差集

>>> s = {1,2,3,4}
>>> t = {3,4,5,6}
>>> s-t				# 注:差集
{1, 2}
>>> s^t				# 注:对称差集
{1, 2, 5, 6}

print(set(ret) ^ set(a))
#结果为 {'/uploads/allimg/170812/1-1FQ2154ZW47.jpg', ………………'/uploads/allimg/170812/1-1FQ2154641G8.jpg', '/uploads/allimg/170812/1-1FQ2152ZUX.jpg'}
#结果为 set()

示例3

方法1
#正则表达式练习
import re
import requests
ws = requests.get('https://www.sucai8.com/')    # 注:requests获取请求
# print(ws.text)              # 注:获取内容
#结果为<html xmlns="http://www.w3.org/1999/xhtml">
#<head>…………………………
#ret = re.findall(r'<img.*(?<=src=")(.+(?:\.jpg))(?=")',ws.text,re.M)		# 注:写错了<img.*贪婪匹配一直匹配 出错
ret = re.findall(r'<img.*?(?<=src=")(.+?(?:\.jpg))(?=")',ws.text,re.M)	# 注:<img.*?非贪婪匹配
# imglist = re.findall(r'(?<=<img)(?:.+?src=")(.+?.jpg)', html,re.M)    # 
p = []
for i in ret:
    if i.startswith("http"):
        p.append(i)
    else:
        j = "https://www.sucai8.com"+i
        p.append(j)
print(p)
print(len(p))   # 注:结果为 19
#结果为 ['https://www.sucai8.com/uploads/allimg/170812/1-1FQ2143HS18.jpg', ……'https://www.sucai8.com/uploads/allimg/170817/1-1FQG405560-L.jpg']
方法2:将文件下载到本地
import re
import requests				# 注:贪婪匹配 非贪婪匹配 +*? 或者{n,m}
ret1 = requests.get("https://www.sucai8.com")	# 注:非贪婪匹配 在* + 后 加 ? 号
a = re.findall(r"(?:src=\")(.*?\.(?:jpg))",ret1.text)	# 注:?:jpg 为了元组只有1个元素
# imglist = re.findall(r'(?<=<img)(?:.+?src=")(.+?.jpg)', html,re.M)    # 
print(a)
# b = re.findall(r"(?:\<a)")
for i in range(len(a)):
    try:
        ret = requests.get(url = f"{a[i]}")
        print(ret.url)
        with open(f"E:/hxli/{i}.jpg","wb") as f:
            f.write(ret.content)
    except Exception as af:
        ret = requests.get(url = f"http:{a[i]}")
        print(ret.url)
        with open(f"E:/hxli/{i}.jpg","wb") as f:
            f.write(ret.content)
ret = re.findall(r'<img.*?(?<=src=")(.+?(?:\.jpg))(?=")',ws.text,re.M)	# 注:推荐
a = re.findall(r"(?:src=\")(.*?\.(?:jpg))",ret1.text)	#注:没有img标签
imglist = re.findall(r'(?<=<img)(?:.+?src=")(.+?.jpg)', html,re.M)#注:写法没错,是匹配的内容错了
imglist = re.findall(r'(?<=<img)(?:.+?src=")(.+?.jpg)', ws.text,re.M)  #
print(imglist)
ret = re.findall(r'<img.*?(?<=src=")(.+?(?:\.jpg))(?=")',ws.text,re.M)
print(ret)
a = re.findall(r"(?:src=\")(.*?\.(?:jpg))",ws.text,re.M)
print(ret)
#结果都是 #['/uploads/allimg/170812/1-1FQ2152ZUX.jpg''/uploads/allimg/170817/1-1FQG405560-L.jpg']

4、获取a标签 href 网址

示例

import re
import requests
ws = requests.get('https://www.sucai8.com')
b = re.findall(r"(?:<a href=\")(.+?)(?:\")",ws.text)		# 注:核心
p = []
for i in range(len(b)):
    if b[i][0] == "/":
        p.append("https://www.sucai8.com/"+b[i])
    elif b[i][0] == "h":
        p.append(b[i])
    else:
        pass
print(len(set(p)))       # 注:去重
ret2 = re.findall(r'(?:<a.*?(?<=href=\"))([/h].*?)(?=\")',ws.text,re.M)	# 注:核心
print(len(set(ret2)))
#结果都是 45个

知识点2 高阶函数

高阶函数
·把函数作为参数传入,这样的函数称为高阶函数,

示例

# 高阶函数
# 把函数作为参数传入,这样的函数称为高阶函数
def func01(a, b):
    print(f"{a} {b}")

func01("x", "y")    # 注:函数的调用;位置参数一一对应
func01(b = "bb", a = "aa")  # 注:关键字参数;参数的传递和接收的位置不需要一一对应;Key=value的形式传参
#结果为 x y
#aa bb
def func02(func,a,b):   # 注:把函数作为参数传递;func02称为高阶函数
    print("start func......")
    func(a,b)

func02(func01,"x","y")
#结果为 start func......
#x y
# def func02(func):
#     print("start func......")
#     func()
# func02(func01)
# 注:报错:func01缺少2个位置的位置参数

知识点3 常用高阶函数-map

用Python-map代码实现:f(x)=x*x
·内置函数map,map()函数接收两个参数,一个是函数,一个是Iterable(可多个),
·map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。

用Python-map代码实现:f(x)=x*x
·map()传入的第一个参数是f,即函数对象本身。
·由于结果r是一个Iterator,Iterator是惰性序列。
·可通过list()函数让它把整个序列都计算出来并返回一个list。

实现方式比较
·map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x**2,还可以计算任意复杂的函数
常用高阶函数-map

示例1

# map 映射
def func(item):         # 接收1个参数item
    return item*item    # 返回数的平方

a = [1,2,3,4,5,6]       # 注:a是可迭代对象
result = map(func, a)
print(result)   # 注:返回 map对象
#结果为 <map object at 0x0000020EDE156970>
print(list(result))
#结果为 [1, 4, 9, 16, 25, 36]
#注:返回的是映射,按照func里面规定的方式做映射,再输出为1个map对象
#注:不可以直接获得map对象,可视化需要转换成list
#注:映射关系(一一对应)
#注:将可迭代对象里的每一个值 按照func来映射
#注:func默认1个参数,不能接收2个参数
a = [1,2,3,4,5,6]
result = map(lambda x:x*x, a)   # 注:匿名函数;:前面接参数,后面接函数体
print(list(result))
#结果为 [1, 4, 9, 16, 25, 36]

示例2 保留2位小数

# 保留2位小数
b = [1.239865,4.56,3.2,9.82356]

#方法1
result = map(lambda x:'%.2f'%x, b)
print(list(result))
#结果为 ['1.24', '4.56', '3.20', '9.82']

#方法2
result = map(lambda x:round(x,2), b)
print(list(result))
#结果为 [1.24, 4.56, 3.2, 9.82]

示例3 转化为百分数,并且保留2位小数

#转化为百分数,并且保留2位小数
c = [0.000564, 0.456723, 0.5, 0.71345]

#方法1 forma函数
result = map(lambda x:format(x,'.2%'), c)
print(list(result))
#结果为 ['0.06%', '45.67%', '50.00%', '71.34%']

#方法2 x*100
result = map(lambda x:'%.2f%%'%(x*100), c)
print(list(result))
#结果为 ['0.06%', '45.67%', '50.00%', '71.34%']

练习4

有列表[1,2,3,4,5],将所有元素转换成str:[‘1’,‘2’,‘3’,‘4’,‘5’]
有列表字符串’span’,将各字符转换成对应的ascii码的列表[115, 112, 97, 109]
有列表[-1,-2,0,1,2],将各元素转换成绝对值[1, 2, 0, 1, 2]

示例

# 有列表[1,2,3,4,5],将所有元素转换成str:['1','2','3','4','5']
a = [1,2,3,4,5]
result = map(lambda x:str(x), a)
print(list(result))

# 有列表字符串'span',将各字符转换成对应的ascii码的列表[115, 112, 97, 109]
b = 'span'
result = map(lambda x:ord(x), b)		# 注:内建函数ord()获取ascii编码
print(list(result))

# 有列表[-1,-2,0,1,2],将各元素转换成绝对值[1, 2, 0, 1, 2]
c = [-1,-2,0,1,2]
result = map(lambda x:abs(x), c)		# 注:内建函数abs()获取绝对值
print(list(result))

知识点5 常用高阶函数-filter

用Python-filter代码实现:在一个list中,删掉偶数,只保留奇数
·Python内建的filter()函数用于过滤序列。和map()类似,filter()也接收一个函数和一个序列
·filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。 # 注:为True保留;为False丢弃
·注意到filter()函数返回的是一个Iterator,也就是一个惰性序列。

#filter 过滤

示例1 保留奇数

#filter 过滤
#保留奇数
a = [1,2,3,4,5,6,7,8]
def func01(x):
    return x % 2 == 1   # 注:保留奇数;返回结果true\false

result = filter(func01, a)
print(list(result))
#结果为 [1, 3, 5, 7]

示例2 返回结果true\false

>>> 3 % 2 == 1
True
>>> 4 % 2 == 1
False

示例3 返回100以内的回数

# 返回100以内的回数    (不包括100)
# 回数 从左至右 和 从右至左 都是一样的

# b = range(1,100+1)    # 注:不能判断 1-9
# def func02(x):
#     return x%11 == 0
# result = filter(func02,b)
# print(list(result))
#结果为 [11, 22, 33, 44, 55, 66, 77, 88, 99]
b = range(1, 101) # 注:字符串反向切片
def func02(x):
    return str(x) == str(x)[::-1]
result = filter(func02, b)
print(list(result))
#结果为 [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99]

示例4:过滤出 1-100 以内 开平方根 是整数的数

方法1:开平方后还在原列表里

# 过滤出 1-100 以内 开平方根 是整数的数
#math,sqrt
from math import sqrt
c = range(1, 101)
result = filter(lambda x:sqrt(x) in range(1, 101) , range(1, 101))
print(list(result)) # 注:开平方后的数还在 c 里面
#结果为 [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

方法2:int取整

from math import sqrt
c = range(1, 101)
def func03(x):  # 注:浮点数的取整
    result = int(sqrt(x))
    return result * result == x
>>> int(2.1)
2
>>> int(3.8)
3

方法3:isdigit 判断

>>> a = "1.2"
>>> a.isdigit()
False
>>> a = "2"
>>> a.isdigit()
True
Python 爬虫中,正则表达式是非常常用的技术,可以帮助我们从网页中提取出需要的信息。下面是一些常用的正则表达式符号和方法: 1. ".":匹配任意单个字符,除了换行符。 2. "^":匹配字符串的开始位置。 3. "$":匹配字符串的结束位置。 4. "*":匹配前一个字符出现 0 次或多次。 5. "+":匹配前一个字符出现 1 次或多次。 6. "?":匹配前一个字符出现 0 次或 1 次。 7. "{m}":匹配前一个字符出现 m 次。 8. "{m,n}":匹配前一个字符出现 m 到 n 次。 9. "(...)":分组匹配,匹配括号内的表达式。 10. "[...]":匹配括号内的任意一个字符。 11. "[^...]":匹配不在括号内的任意一个字符。 12. "\d":匹配数字,等同于 [0-9]。 13. "\D":匹配非数字,等同于 [^0-9]。 14. "\s":匹配空白字符,包括空格、制表符、换行符等。 15. "\S":匹配非空白字符。 16. "\w":匹配单词字符,包括字母、数字、下划线。 17. "\W":匹配非单词字符。 在 Python 中,使用 re 模块进行正则表达式的匹配。常用的方法包括: 1. re.compile(pattern):将正则表达式编译成一个对象,提匹配效率。 2. re.search(pattern, string):在字符串中搜索匹配正则表达式的第一个位置。 3. re.findall(pattern, string):在字符串中搜索匹配正则表达式的所有位置,并返回一个列表。 4. re.sub(pattern, repl, string):将字符串中所有匹配正则表达式的字符替换为指定的字符串。 以上是一些常用的正则表达式符号和方法,希望能对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mycpen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值