Python处理邮件内容和提取邮件里的url地址
最近在搞一个邮箱验证账号注册和登录的模块。总结一下。就当记载。文章中涉及到域名和邮箱等都经过处理。
需求是这样子的,通过selenium注册某个网站的账号,然后注册需要邮件内容里的链接激活,登录的时候如果不是常用设备的话也需要认证,而两种认证方式给出的链接方式是不一样的。一种是直接通过发放激活链接给你,就是纯网址,这个好处理,直接用str或者text就能从邮件内容里将原始的url地址提取出来了。但是登录认证的话就是一个锚文本链接,这个如果还用str或者text方式提取的话,就会出现一个问题,就是提取出来的url里的"&"它会变成"&",在浏览器地址栏中输入的话,就会出错。所以用str或者text方式提取出来的,还得还原一下地址栏能用的网址。用模块html就行了。所有问题搞定。然后将提取出来的链接加载到selenium里继续愉快的xxoo就行了。
思路:1->登录邮箱;
2->获取最新邮件(获取最新邮件的理由是,激活和认证的同时,应该不会那么巧有其他邮件发过来,所以我觉得,这种足够满足需求了);
3->解析邮件内容,用imap和pop取回来的邮件我嫌太麻烦,用国人大神开发的zmail解析邮件内容只需几个步骤。
首先获取邮件的html内容
将html内容解析成str
把str内容单独提取出来,在本地建一个html页面
通过bs4解析这个本地html的内容
提取自己想要的内容,在这里是链接地址
提取激活链接的代码:
1 import zmail 2 from bs4 import BeautifulSoup 3 import lxml 4 5 ''' 6 #一个模块专门处理xxx新注册用户的邮箱验证问题 7 #思路: 8 1,首先通过zmail登录到邮箱 9 2,因为注册都是即时的,验证邮件应该也是即时的 10 3,收取最新收到的邮件 11 4,获取最新邮件的content_html内容 12 5,将content_html内容转换成str格式方便处理 13 6,将str格式的html文档使用bs4解析 14 7,通过bs4解析出来的内容是一个列表 15 8,读取列表里的文本内容,这样子也不会丢失格式 16 #坑: 17 1,邮箱里的链接内容如果通过直接读取,是会更改的,比如说=就会变成amp等,所以要通过text读取 18 19 20 ''' 21 class GetTheVerifyLink(): 22 def __init__(self, emailAccount, pwd): 23 #初始化用户名和密码 24 self.emailAccount = emailAccount 25 self.pwd = pwd 26 27 def login_to_server(self): 28 ''' 29 #尝试登录邮箱服务器 30 ''' 31 try: 32 connect = zmail.server(self.emailAccount, self.pwd) 33 print("登录成功!") 34 except: 35 print("登录失败!请检查") 36 #将connect对象返回到调用它的代码行 37 return connect 38 39 def get_the_latest_mail(self): 40 ''' 41 #通过判定最新邮件的发件人是不是有xxx来判定是不是我们要的邮件 42 ''' 43 mail = self.login_to_server().get_latest() 44 #开始判定 45 sender = mail['From'] #获取发件人 46 subject = mail['Subject'] #获取邮件主题 47 content_text = mail['Content_text'] #获取邮件内容 48 content_text_str = ''.join(content_text) #将邮件内容转换为str,不转换也行,不转换请看下面 49 # content_text_str = ''.join(content_text[0]) #获取列表的一个元素,将它转换成str,因为它只有一个元素 50 if '@xxx' in sender and 'verify your e-mail address' in subject and 'https://www.xxx/xx/xxx' in content_text_str: 51 print("这是我们需要的邮件!") 52 return mail 53 else: 54 print("这不是我们需要的邮件,请登录邮箱手动删除并保持amazon认证邮件最新!") 55 56 def get_the_mail_content_html(self): 57 content_html = self.get_the_latest_mail()['content_html'] 58 if content_html: 59 return content_html 60 else: 61 print("获取content_html内容邮件失败!") 62 63 def tranfer_content_html_to_str(self): 64 content_html_to_str = ''.join(self.get_the_mail_content_html()) 65 if content_html_to_str: 66 print("将邮件的content_html转换成str成功!") 67 return content_html_to_str 68 else: 69 print("将邮件的content_html内容转换成str失败!") 70 71 def get_the_verify_link(self): 72 soup = BeautifulSoup(self.tranfer_content_html_to_str(), 'lxml') 73 verify_link_list = soup.select(r'body > p:nth-child(3) > a:nth-child(1)') 74 for verify_link in verify_link_list: 75 verify_link = verify_link.text 76 return verify_link 77 78 # emailAccount = 'xxx@xxx.com' 79 # pwd = 'xxxx!' 80 # 81 # gt = GetTheVerifyLink(emailAccount,pwd) 82 # # latest_mail = gt.get_the_latest_mail() 83 # # print(latest_mail) 84 # verify_link = gt.get_the_verify_link() 85 # print(verify_link)
提取登录链接的代码:
1 import zmail 2 from bs4 import BeautifulSoup 3 import lxml 4 import html 5 6 class xxxSignInConfirm(): 7 def __init__(self, username, password): 8 self.username = username 9 self.password = password 10 11 def login_to_server(self): 12 try: 13 server = zmail.server(self.username, self.password) 14 print("E-mail Login success!") 15 except: 16 print("E-mail login Failed!") 17 return server 18 19 def get_the_latest_mail(self): 20 ''' 21 #通过判定最新邮件的发件人是不是有xxx.com来判定是不是我们要的邮件 22 ''' 23 mail = self.login_to_server().get_latest() 24 #开始判定 25 sender = mail['From'] #获取发件人 26 subject = mail['Subject'] #获取邮件主题 27 content_text = mail['Content_text'] #获取邮件内容,获取文本的邮件内容主要是用在接下来的if语句里的 28 content_text_str = ''.join(content_text) #将邮件内容转换为str,不转换也行,不转换请看下面 29 # content_text_str = ''.join(content_text[0]) #获取列表的一个元素,将它转换成str,因为它只有一个元素 30 if 'security' in subject: 31 print("这是我们需要的邮件!") 32 return mail 33 else: 34 print("这不是我们需要的邮件,请登录邮箱手动删除并保持amazon认证邮件最新!") 35 36 def get_the_mail_content_html(self): 37 mail = self.get_the_latest_mail() 38 content_html = mail['Content_html'] 39 if content_html: 40 return content_html 41 else: 42 print("获取content_html内容邮件失败!") 43 44 def transfer_content_html_to_str(self): 45 content_html_to_str = ''.join(self.get_the_mail_content_html()) 46 if content_html_to_str: 47 print("将邮件的content_html转换成str成功!") 48 return content_html_to_str 49 else: 50 print("将邮件的content_html内容转换成str失败!") 51 52 def get_the_sign_in_verify_link(self): 53 soup = BeautifulSoup(self.transfer_content_html_to_str(), 'lxml') #利用bs4解析html的邮件内容 54 signInconfirmLinks = soup.select(r'body > div:nth-child(3) > div:nth-child(4) > table:nth-child(2) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(1) > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(5) > td:nth-child(1) > a:nth-child(1)') 55 signlinkelement = signInconfirmLinks[0] 56 signlinkstr = str(signlinkelement) #转换成str 57 # print(signlinkstr) 58 afind = signlinkstr.find('"') #查找字符串中<a href="https//xxxxxxxx.com/"</a>的第一个引号 59 # print(afind) 60 bfind = signlinkstr[afind + 1:].find('"') #找出第二个引号的位置 61 # print(bfind) 62 signlinkamp = signlinkstr[afind + 1: afind + 1 + bfind] #在两个引号之间就是我们需要的链接地址,切片切出来 63 # print(signlinkamp) #打印一下提取出来的地址,是我们想要的,只是&变成了& 64 verify_link = html.unescape(signlinkamp) #使用html还原真实网址 65 return verify_link 66 67 username = 'xxxx@xxx.com' 68 pwd = 'xxxx' 69 ac = AmazonSignInConfirm(username, pwd) #实例化 70 71 72 verify_link = ac.get_the_sign_in_verify_link() 73 print(verify_link) #打印,符合预期
两段代码基本上是相同的,除了最后一个类方法处理方式有点不同的话。文中有些合法性验证是不需要的,我是为了方便调试和查看程序运行轨迹才加那么多的。记录是记录,也希望有志同道合的人,给出更完美的解决方案。