【Python 爬虫】正则表达式的简单使用

一、综述

  1. 为什么要学正则:处理数据(按照我们想要的方式存储和使用)
  2. 正则匹配规则:因为太长了,所以见本文最后
  3. match方法:从起始位置开始查找,一次匹配,返回object对象,使用group()获取对象中存储的匹配值
  4. search方法:从任何位置开始查找,一次匹配,返回object对象,使用group()获取对象中存储的匹配值
  5. findall方法:全部匹配,返回列表,若匹配表达式,要求同时还有其他匹配,则返回元组列表,r'<img src2="(.*?)" alt="(.*?)"'
  6. finditer方法:全部匹配,返回迭代器,迭代器每次迭代,都会返回object对象,使用group()获取对象中存储的匹配值
  7. split方法:分割字符串,返回列表
  8. sub方法:替换
  9. 匹配中文:re.compile(u'[\u4e00-\u9fa5]+')
  10. 贪婪模式与非贪婪模式

二、如何使用

用法:

  1. 根据匹配规则定义pattern : pattern=re.compile(r’匹配规则’) 或者直接 pattern = r’匹配规则’
  2. 使用re,根据匹配规则在对应的字符串中寻找符合匹配的:result=re.match(pattern,‘待匹配字符串’)
  3. 若返回对象,则用group获取;若返回列表,可直接读取;若返回迭代器,用循环获取,再用group

三、方法介绍

import re

s1 = 'hello world python high salary 123 456 Hello 789'
s2 = '235 hello world python high salary 123 456 Hello 789'

pattern = re.compile(r'\d+')
# match
print('*'*25,'match','*'*25)
result1 = re.match(pattern,s1)
result2 = re.match(pattern,s2)
print(result1)
print(result2)
print(result2.group())

# search
print('*'*25,'search','*'*25)
result3 = re.search(pattern,s1)
print(result3)
print(result3.group())

# findall
print('*'*25,'findall','*'*25)
pattern1 = re.compile(r'\w+')
result4 = re.findall(pattern1, s1)
print(result4)

# finditer
print('*'*25,'finditer','*'*25)
result5 = re.finditer(pattern, s1)  # 返回可迭代对象,迭代器
for r in result5:
    print(r)
    print(r.group())

# split
print('*'*25,'split','*'*25)
s3 = '235 hello world python high salary 123 456 Hello 789'\
    'this is the second line'\
    'this is the third line'
pattern2 = re.compile(r'[\s.,\n]')
result6 = re.split(pattern2, s3)
print(result6)

# sub
print('*'*25,'sub','*'*25)
s4 = 'Hello World,Hello Python'
pattern3 = r'(\w+) (\w+)'
result7 = re.sub(pattern3, r'\2 \1', s4)
print(result7)

def convert(m):
    return m.group(2).lower() + ' '+ m.group(1).upper()

result8 = re.sub(pattern3, convert, s4)
print(result8)

结果:
在这里插入图片描述
上述一堆方法中,最常用的还是findall方法,所以熟悉findall方法很重要

四、对findall方法的详细说明

import re
url= '<img src2="http://pic.sc.chinaz.com/Files/pic/pic9/201911/zzpic20859_s.jpg" alt="秘密图片">'
pattern = r'<img src2="(.*?)"'
print(re.findall(pattern,url))
print(re.match(pattern,url).group())

上述代码,使用的是同样的pattern,但是对于findall和match返回的是不一样的:
在这里插入图片描述
可以看到findall直接就返回分组的内容,而match这类返回object对象的,返回的是完整的匹配项

import re
td = '<td class>192.168.1.1</td>'
pattern1 = r'<td .*?>([\d\.]*)</td>'
pattern2 = r'<td (.*?)>([\d\.]*)</td>'
print(re.findall(pattern1,td))
print(re.findall(pattern2,td))

在这里插入图片描述
对于上述代码,我们可以看到,虽然都是findall,但是当class匹配项,不在分组内的时候,即使匹配也是不返回的。

import re
td = '<td class>192.168.1.1</td>'
pattern1 = r'<td .*?>[\d\.]*</td>'
print(re.findall(pattern1,td))

在这里插入图片描述
可以看到,上述代码,当没有分组出现的时候,返回的也是完整的匹配项

综上,使用findall结合分组的方法,可以很方便的获取一些src路径,这样就省去了将完整匹配项分割来取src的麻烦

即:对于定义了分组的,即匹配内容有()的

  1. 返回列表的,仅仅返回的分组内匹配内容
  2. 返回对象的,返回的全部匹配内容(包括分组内,分组外)

如:

<img src2="http://pic.sc.chinaz.com/Files/pic/pic9/201911/zzpic20859_s.jpg" alt="秘密照片">
pattern = r'<img src2="(.*?)"'
finditer,match,search 返回 <img src2="http://pic.sc.chinaz.com/Files/pic/pic9/201911/zzpic20859_s.jpg"
findall 返回 http://pic.sc.chinaz.com/Files/pic/pic9/201911/zzpic20859_s.jpg

五、实战爬取网页的时候,一个注意事项

re.S的使用,忽略换行符的影响

re.S是正则表达式中匹配的一个参数,如果没有re.S,则是只匹配一行有没有符合规则的字符串,如果没有则下一行重新匹配。

如果加上了re.S,则是将所有的字符串按一个整体进行匹配,findall将所有匹配到的结果封装到一个list中

re.findall(str_pattern, str, re.S)

在这里插入图片描述

六、正则匹配规则

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

七、实战:批量爬取图片

import requests
import re
import time
import random

# 爬取站长素材网站图片

url1 = 'http://sc.chinaz.com/tupian/xingganmeinvtupian.html'
url2 = 'http://sc.chinaz.com/tupian/xingganmeinvtupian_%d.html'


def download_imgs(result):
    for url, name in result:
        response = requests.get(url=url)
        with open('./picture_download/%s.jpg' % name, mode='wb') as fp:
            fp.write(response.content)
        time.sleep(random.randint(1, 3))  # 随机休眠1到3秒


if __name__ == '__main__':
    pic_url = []
    for index in range(1, 2):
        if index == 1:
            url_tmp = url1
        else:
            url_tmp = url2 % index
        response = requests.get(url_tmp)
        response.encoding = response.apparent_encoding
        pattern = r'<img src2="(.*?)" alt="(.*?)"'
        result = re.findall(pattern,response.text)
        download_imgs(result)
    print('ok')
    # with open('./picture.html', mode='w', encoding='utf-8') as fp:
    #     fp.write(response.text)
    #     print('已写入')

上述代码会爬取网络上的图片,出彩的亮点是findall一次匹配两个分组,这样返回的就是一个元组,即result是一个元组列表,列表中的每一个元组的第一项是正则中的第一个分组,第二项是正则中的第二个分组

另外一个亮点是,爬虫中经常用到的手段,随机休眠:time.sleep(random.randint(1, 3)) # 随机休眠1到3秒 可以防止被封IP

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值