正则与爬虫(1)

正则是什么

正则是一门小型的编程语言,在python中正则被封装成re模块。自己对正则的理解就是用来匹配字符串中一些字符,正则使得匹配字符串的匹配更加多样。

三种匹配方法

re模块中匹配了三种方法(findall,match,search)

s = "/home/kioskday25/PycharmProjects/python_stack/day25/正则表达式的正常使用符那方法.py"
pattern = r'day'
pattern1 = r'/home'

print(re.findall(pattern,s))
#注意:findall会匹配子符串中所有的字符,并以列表的形式把他们列出来
print(re.match(pattern1,s).group())
#注意:match方法只匹配字符串的开头:
#当在开头匹配到字符串时,返回一个对象,如果要查看匹配的结果,需要借用group方法,gruop方法返回的是一个字符串
#当没有匹配到结果时返回一个空
print(re.search(pattern,s).group())
#注意:search方法匹配的是整个字符串,当字符串中有多个满足匹配结果时,只匹配第一个,并通过gruop方法获取到匹配的结果。

结果如下:
在这里插入图片描述

正则特殊字符类


#.:匹配除\n之外的任意字符,并将每个匹配到的字符通过列表存储
print(re.findall(r'.','westos\n'))


#\d:匹配一个数字,等加于[0-9]
#\D:匹配除数字外的任意一个字符
print(re.findall('\d','python12345linux'))
print(re.findall('\D','python12345linux'))


#\s:匹配单个任何空白的字符
#\S:匹配除单个任何空白字符的任何字符
print(re.findall('\s',"python\r123\tlinux"))
print(re.findall('\S',"python\r123\tlinux"))


#\w:匹配字母数字或下划线
#\W:匹配除字母数字下划线的字符
print(re.findall('\w',"python_123_linxu%%%%@@@"))
print(re.findall('\W',"python_123_linxu%%%%@@@"))

print(re.findall('[1-5][0-9]','123456'))
pattern = r'[ABC][]'

注意:在findall方法中,匹配返回的结果是一个列表。
结果:
在这里插入图片描述

在上面的匹配中,如果我们要匹配一个数字,那我们就必须写多次\d,显得非常麻烦。在正则中,我们可以利用一个语法实现实现\d多次,免去多次书写的麻烦。


#*代表前面的字符出现0次或者无限多次
print(re.findall("\d*",'132233'))

#+代表前面的字符出现一次或者无限次
print(re.findall("\d+",'122245'))

#?代表一个字符出现1次或者0次
print(re.findall("\d?","123455"))

#{m}:前一个字符出现m次
#{m,}:前一个字符至少出现m次
#{m,n}:前一个字符出现m次到n次

pattern = r"[a-zA-z][\w]{5,11}@qq\.com"
print(re.findall(pattern,'a1905050@qq.com'))

结果:
在这里插入图片描述

转义字符

|:匹配左右任意一个表达式即可
print(re.findall(r"(westos|hello)\d+",'westoshello446'))
在这里插入图片描述
(mn):将括号里面的内容作为一个分组

s = '<span class="red">31</span>'
print(re.findall(pattern,s))


pattern1 = r'(<span class="red">(\d+)</span>)'
s = '<span class="red">31</span>'
print(re.findall(pattern1,s))


print(re.findall(r'((westos|hello)\d+)',"westos1hello2"))
#把匹配到的内容分成组,每组以元组的形式存储

\num:引用分组第num个字符串
(?P):分组起别名

爬去贴吧中的qq邮箱

分析:实现这个效果要利用正则表达式,对得到的网页源码进行匹配操作。
代码可分为以下几个模块:

  • 获取源码:对网页的内容进行爬取,并进行解码
  • 获取网页的页数:写一个正则表达式,从获取到的源码中获取到贴吧的总页数。
  • 获取邮箱:写一个邮箱的正则表达式,从获取到的的源码中获取到邮箱,具体为先获取到页数,然后利用循环对每一页的源码进行获取,然后对源码进行一个邮箱的提取操作,。
  • 主函数:调用上面几个函数,然后把函数返回的邮箱地址,写入文件中。
from itertools import chain
from urllib.request import urlopen

def getPageHtml(url):
   #获取网页的源码文件
   obj = urlopen(url)
   return obj.read().decode('utf-8')

#print(getPageHtml("http://tieba.baidu.com/p/3600458679"))

'''<li class="l_reply_num" style="margin-left:8px" ><span class="red" style="margin-right:3px">1193</span>回复贴,共<span class="red">26</span>页</li>'''
def getPagenum(text):
   #从源码文件中获取,总页数
   pattern = r'<span class="red">(\d{0,3})</span>'
   return re.findall(pattern,text)[0]

#text = getPageHtml("http://tieba.baidu.com/p/3600458679")
#print(getPagenum(text))

'''http://tieba.baidu.com/p/3600458679?pn=2'''
def getPageEMail(count):
   #对所有页数的文件挨个进行爬取,并利用正则表达式从源码中,匹配到信息
   mails = []
   for i in range(int(count)):
       url = "http://tieba.baidu.com/p/2314539885?pn=%d" %(i+1)
       text = getPageHtml(url)
       #<li class="d_name" data-field='{&quot;user_id&quot;:1159023837}'>
       #811393332@qq.com
       pattern1 = r'\d{5,12}@qq\.com'
       print("正在爬取http://tieba.baidu.com/p/3600458679?pn=%d的内容" %(i+1))
       print(re.findall(pattern1,text))
       mails.append(re.findall(pattern1,text))
   return mails


def main():
   text = getPageHtml("http://tieba.baidu.com/p/2314539885")
   count = getPagenum(text)
   email = getPageEMail(count)
   #chain 方法是对不同集合中的元素进行操作时,将不同的列表连接起来
   with open("mails.txt",'w') as f:
       for i in chain(*email):
           f.write(i+"\n")
main()

结果:
在这里插入图片描述

爬取图片

from urllib.request import urlopen


def getPageHtml(url):  #获取网页的源码
    obj = urlopen(url)  
    return obj.read()

def getPagepic(text):  
#从网页的源码中获取到图片的网址,返回的是一个列表,列表里面存储的是当前网页的所有图片的地址
    pattern ='<img class="BDE_Image" .*?src="(http://.*?\.jpg)".*?>'
    return re.findall(pattern,text.decode('utf-8'))


url = "http://tieba.baidu.com/p/5904388543"
text = getPageHtml(url)  
picurl = getPagepic(text)  
#对存有图片地址的列表进行一个遍历,依次对图片的网址打开进行一个获取图片。
for i,v in enumerate(picurl):
    with open("img/img%d.jpg" %(i+1),"wb") as f:
        content = getPageHtml(v)
        print("正在爬取第%d张图片" %(i+1))
        f.write(content)

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值