Loading

爬虫(四)数据清洗-正则表达式

正则表达式介绍

正则表达式

即,数据筛选的表达方式(匹配)

import re

strr = "张三李四王五赵六"

pat = "王五" # 正则表达式

rst = re.search(pat,strr)

print(rst)

 

体验-分析《天龙八部》主角到底是谁

import re

with open(r"C:\\Users\\Administrator\\Desktop\\tianlong.txt","rb") as f:
    data = f.read().decode()

pat1 = "乔峰"
pat2 = "萧峰"
pat3 = "乔帮主"
pat4 = "段誉"
pat5 = "虚竹"

n1 = re.findall(pat1,data)
n2 = re.findall(pat2,data)
n3 = re.findall(pat3,data)
n4 = re.findall(pat4,data)
n5 = re.findall(pat5,data)

print("乔峰出现次数:",len(n1)+len(n2)+len(n3),"段誉出现次数:",len(n4),"虚竹出现次数:",len(n5))

 

匹配普通字符

原子:正则表达式中实现匹配的基本单位

元字符:正则表达式中具有特殊含义的字符

 

以普通字符作为原子(匹配一个普通字符)

import re

a = "湖南湖北广东广西"

pat = "湖北"

result = re.search(pat,a)

print(result)

 

匹配通用字符

匹配通用字符

  • \w 任意字母、数字、下划线
  • \W 和小写w相反
  • \d 十进制数字
  • \D 除了十进制以外的值
  • \s 空白字符
  • \S 非空白字符
import re


b = "13617054927"

part = "\d\d\d\d\d\d\d\d\d\d\d"

result = re.search(part,b)

print(result)

 

import re


# b = "13617054927"
#
# part = "\d\d\d\d\d\d\d\d\d\d\d"
#
# result = re.search(part,b)
#
# print(result)

c1 = "fj2d9fj92jfoejf934jtoerjgfosjgo3u0t34"

c2 = "@@@@@@@@2jfoejf934jtoerjgfosjgo3u0t34"

part = r"\w\w\w"

print(re.search(part,c1))
print(re.search(part,c2))

 

 

匹配数字、中文、英文

数字:[0,9]

英文:[A-Z][a-z]

中文:[\u4e00-\u9fa5]

import re

# 数字:[0,9]
# 英文:[A-Z][a-z]
# 中文:[\u4e00-\u9fa5]

d = "f920U)F)jf302rk3fkrelgb即300为热裤股票开盘部分的可怕扩容394u093rfj34ofH"

part1 = r"[0,9][0,9]"
part2 = r"[a-z][a-z]"
part3 = r"[\u4e00-\u9fa5][\u4e00-\u9fa5]"

result1 = re.search(part1,d)
result2 = re.search(part2,d)
result3 = re.search(part3,d)

print("result1:",result1,"result2:",result2,"result3:",result3)

 

原子表

原子表:是定义一组平等的原子,这组原子中,只要有一个满足条件那就匹配成功

import re


b = "13822748902"

part = "1[3572]\d\d\d\d\d\d\d\d\d" # 可以匹配以1开头第二位3、5、7或2的数字

print(re.search(part,b))

c = "djfoejfoj4pychonrj4oj43o9r034"

part2 = r"py[abcdt]hon" # 可以匹配以py开头后面a\b\c\d\t当中满足任意一个即可

print(re.search(part2,c))

 

常用元字符

 元字符:正则表达式中具有特殊意义的字符

  • · . 匹配任意字符 \n除外
  • · ^ 匹配字符串开始的位置 ^136
  • · $ 匹配字符串结束的位置 6666$
  • · * 重复0次1次多次前面的原子 /d*
  • · ? 重复一次或者多次前面的原子 /d?要么有1个数字或者多个数字
  • · + 重复一次或多次前面的原子 /d+
import re

d = "135594384390909583998883848392"

part1 = "..."
part2 = "135\d\d\d\d\d\d\d\d"
part3 = ".*8392$"
part4 = "8*"
part5 = "8+"


print("part1:",re.search(part1,d))
print("part2:",re.search(part2,d))
print("part3:",re.search(part3,d))
print("part4:",re.search(part4,d))
print("part5:",re.search(part5,d))

 

匹配固定次数

 我们需要元组固定出现多少次

 

{n} 前面的原子出现了n次

{n,} 至少出现n次

{n,m} 出现次数介于n-m之间

import re

a = "2345654jisw"

part1 = r"\d{6}"
part2 = r"\d{4,}" # 至少4位字符
part3 = r"\S{8,10}" # \S 非空白字符


print(re.search(part1,a))
print(re.search(part2,a))
print(re.search(part3,a))

 

匹配多个正则表达式

 多个表达式

import re

a = "13409537832"
b = "021-8333627"

part1 = r"1[3578]\d{9}"
part2 = r"\d{3}-\d{7}"

part3 = r"1[3578]\d{9}|\d{3}-\d{7}" # 满足两个正则表达式

print(re.search(part1,a))
print(re.search(part2,b))

print(re.search(part3,a))
print(re.search(part3,b))

 

分组

import re

# 分组()

a = "jiwdfdjskjfoe#pythonR$Wr2roef2#rjavafdsfe#$@$FSFWFDS13876439027FSF#@$RGFSA@$34"

part1 = r"python.{0,}java.{0,}1[3578]\d{9}"

part2 = r"(python).{0,}(java).{0,}(1[3578]\d{9})"

part3 = r"FDS(.*?)FSF"

print(re.search(part1,a))

print(re.search(part2,a).group(1)) # 1表示第一个分组python
print(re.search(part2,a).group(2)) # 2表示第一个分组java
print(re.search(part3,a).group(1)) # 只获取括号内的电话号码
print(re.findall(part3,a)) # 只获取括号内的电话号码

 

贪婪模式和非贪婪模式

 贪婪模式:在整个表达式匹配成功的前提下,尽可能多的匹配

非贪婪模式:在整个表达式匹配成功的前提下,尽可能少的匹配

 

python里默认是贪婪的

import re

strr = "aa<div>test1</div>bb<div>test2</div>cc<div>test3</div>dd"

part1 = r"<div>.*</div>"

part2 = r"<div>.*?</div>" # 加上问好 就是【非贪婪模式】

part3 = r"<div>(.*?)</div>"

print(re.search(part1,strr)) # 贪婪模式
print(re.search(part2,strr)) # 非贪婪模式
print(re.findall(part3,strr))

 

compile函数

 compile函数--将正则表达式转换成内部格式,提高执行效率

import re

strr = "Python666java"

part1 = r"\d+"

part2= re.compile(r"\d+")

part3= re.compile(r"python",re.I) # re.I模式修正符:忽略大小写

print(re.search(part1,strr))
print(part2.search(strr))
print(part3.search(strr))

 

match函数和search函数

· match函数-匹配开头

· search函数-匹配任意位置

这两个函数都是一次匹配,就是说匹配到一次就不再匹配了

import re


strr = "pythonjavahtmljs"

part1 = re.compile(r"python")

part2 = re.compile(r"java")

print(part1.match(strr))

print(part2.search(strr))

print(part1.match(strr).group())

 

findall()函数finditer()函数

· findall() 查找所有匹配的内容,装到列表中

· finditer() 查找所有匹配的内容,装到迭代器中

迭代器:可以用for循环取出来

import re

strr = r"hello-----------------------------------\------------------\--------hello--hello-----------------hello----------\hello------"


part1 = re.compile(r"hello")

print(part1.findall(strr)) # findall效率更高一些

data = part1.finditer(strr)

list1 = []

for i in data:
    print(i.group())
    list1.append(i.group())

print("list:",list1)

 

split()函数和sub()函数

 · split() 按照能够匹配的子串将字符串分割后返回列表

· sub() sub方法用于替换

import re


strr1 = "张三,李四,,,王五,,,,,,赵六"

part1 = re.compile(r",+")

result1 = part1.split(strr1)

print(result1)


strr2 = "hello 123,hello 456"

part2 = re.compile(r"\d+")

result2 = part2.sub("666",strr2) # sub()里传两个参数

print(result2)

 

爬取网站电话号码

 http://changyongdianhuahaoma.51240.com/

import requests
import re

#构造请求头信息
header={
"User-Agent":"Mozilla/5.0 (Linux; U; An\
droid 8.1.0; zh-cn; BLA-AL00 Build/HUAW\
EIBLA-AL00) AppleWebKit/537.36 (KHTML, l\
ike Gecko) Version/4.0 Chrome/57.0.2987.13\
2 MQQBrowser/8.9 Mobile Safari/537.36"
}

url = "http://changyongdianhuahaoma.51240.com/"

response = requests.get(url,headers=header).text

part1 = r'<tr bgcolor="#EFF7F0">[\s\S]*?<td>(.*?)</td>[\s\S]*?<td>[\s\S]*?</td>[\s\S]*?</tr>'
part2 = r'<tr bgcolor="#EFF7F0">[\s\S]*?<td>[\s\S]*?</td>[\s\S]*?<td>(.*?)</td>[\s\S]*?</tr>'

pattern1 = re.compile(part1)

pattern2 = re.compile(part2)

data1 = pattern1.findall(response)
data2 = pattern2.findall(response)

# print(data1)
# print(data2)

resultList = []
for i in range(0,len(data1)):
    resultList.append(data1[i]+data2[i])

print(resultList)

 

爬取豆瓣电影排行榜

import re
import requests
import time

# 首 页html-url  http://movie.douban.com/top250?start=0&filter=
# 第2页html-url  http://movie.douban.com/top250?start=25&filter=
# 第2页html-url  http://movie.douban.com/top250?start=50&filter=

header = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
}

resultList = []

for i in range(1,11):
    url = "http://movie.douban.com/top250?start=" + str((i-1)*25) + "&filter="

    response = requests.get(url,headers = header).text

    part1 = r'<em class="">(.*?)</em>[\s\S]*?<a href="https://movie.douban.com/subject/[\s\S]*?/">[\s\S]*?<img width="100" alt="[\s\S]*?" src'
    part2 = r'<em class="">[\s\S]*?</em>[\s\S]*?<a href="https://movie.douban.com/subject/[\s\S]*?/">[\s\S]*?<img width="100" alt="(.*?)" src'

    parttern1 = re.compile(part1)
    parttern2 = re.compile(part2)

    data1 = parttern1.findall(response)
    data2 = parttern2.findall(response)


    for k in range(0,len(data1)):
        resultList.append(data1[k]+data2[k])

print(resultList)

 

posted @ 2020-08-10 18:16  Binzichen  阅读(462)  评论(0)    收藏  举报