爬取163网页收件箱列表 有几个小问题未解决.

2020-02-13  本文已影响0人  花___

可以说这是一个需求吧, 因为只接触过一点Python, 所以大部分代码基于python-爬虫:获取163邮箱的收件箱信息列表, 其中的代码根据我的需求进行了部分更改, 核心部分并没有做更改. 整体代码不做解释, 因为目前还不会. 具体可以查看之前提到的文章.

需求是需要登录好几个账号进行查看, 看一下有没有收到指定查找的邮件, 所以想着通过python直接拉取看结果会快一点, 于是有了下文.


此文仅做自我记录.

另外有几个问题想请教一下, 路过的围观一下:

  1. 这段代码在win平台中运行不会报错, 但是切换到mac上之后会报错, 具体错误看不懂, 好像是request模块的问题. 因为最终使用实在mac平台上的, 刚开始以为通用, win平台码代码, 测试方便, 所以直接就开改了.
  2. 通过py2apppyinstaller 进行程序的打包, 打包过程中没有任何报错, 最后执行文件都生产了, 但是无法运行, 打开失败.

这两个问题在网上找了好一会儿, 也没有找到解决方案. 先记录着, 后面再回过头来看.


代码中比较关键的部分应该是sid的动态提取, 因为163邮箱在登陆时做了一些动态验证, 如果做不到sid的获取, 邮箱的登录会无法进行.

在下面贴出的源代码中, 存在几个问题, 在此处进行说明:

1. 在时间的解析上存在问题

获取邮件信息部分,message作为承载信息的列表, 在核心代码中获取到的时间信息有误, 邮件本身时间为2018-02-28, 但是在获取到的时候月份上晚了一个月(2018-01-28)的时间, 暂时未找到原因.

由于没办法理解核心代码, 就目前情况而言, 总体不影响代码的使用, 所以在后面使用了一些数据的重组来解决这个问题.

思路是: 列表里面存了n封邮件(即n个元组), 将元组进行打撒, 然后截取有用的时间信息进行重新整合, 并在月份上进行加一处理, 而手动的月份加一就会导致碰到2019年12月份的时候就会变成2019年13月, 虽然可以通过月份的条件判断来解决这个问题, 但是由于邮箱里没有十月份之后的邮件进行检测, 暂时先这样.

        # 解析日期有问题,手动加1;
        list_final_end = []
        for i in range(0, len(mails)):
            list_new = mails[i]
            list_temp = list_new[0:3]
            list_temp_add = list_new[i][3][9:18]
            if list_temp_add[-1:] in range(0, 9):
                months = int(list_new[3][14:16])+1
                months = str(months)
                list_temp_add = [list_new[3][9:13]+months+list_new[3][17:19]]
            else:
                months = int(list_new[3][14:15])+1
                months = str(months)
                list_temp_add = [list_new[3][9:13]+'0'+months+list_new[3][16:18]]
            list_final = [list_temp + tuple(list_temp_add)]
            list_final_end += list_final
        # 打印邮件
2. 指定月份邮件的提取

原本的需求是只要查看最近的邮件就可以了, 因为经常会查看, 所以并不需要很久的邮件, 如果邮箱里有很多的邮件话会拉出来很多信息, 所以对代码上加了一段年月份判断进行筛选当月的邮件.

思路是: 通过导入time模块来获取当前的年份和月份, 再从拉取并重组后的邮件数据中提取年月, 按照年->月的先后顺序进行筛选, 只提取当月的邮件. 但因为是提取的当月的邮件, 所以月底最后一天不允许的话就会漏掉这些邮件, 比较尴尬. 当然, 其实简单点的话可以在获取到需要的信息之后, 再做单独的判断来进行对应的筛选.

        # 打印邮件
        print('*' * 50)
        print('*' * 50)
        print('开始打印收件箱列表.')
        print('登录邮箱:', self.username)
        print('收件列表如下:')
        print('*' * 50)
        print('*' * 50)
        for mail in list_final_end:
            today_year = time.strftime("%Y", time.localtime())  #获取当前年份
            today_month = time.strftime("%m", time.localtime()) #获取当前月份
            mail_year = mail[3][0:4]    #从数据中提取邮件的年份
            mail_month = mail[3][4:6]   #从数据中提取邮件的月份
            if mail_year == today_year:     # 年份对比
                if mail_month == today_month:   #月份对比
                    print('发送时间:', mail[3], '-', '主题:', mail[2], '-', '发件人:', mail[0])
                    print('-' * 50)
                else:
                    pass
            else:
                pass
3. 未知问题

还有部分问题未进行验证, 但目前不影响代码的运行, 因为测试的邮件只有个位数, 所以没办法做到测出其他的问题.
例如list_temp_add = list_new[i][3][9:18]这句代码, 输出的话是一个空值, 前期测试是有的, 但是改着改着就没了, 暂时没有进行其他的测试.

代码运行结果的话可以参考下图:

源代码如下:

# -*- coding:utf-8 -*-

import urllib.request
import re
import http.cookiejar
import urllib.parse
import time
import os

class MAIL:

   #初始化
   def __init__(self):
       #获取登录请求的网址,这个是通用的,只是一个请求登陆的URL
       self.loginUrl = "https://mail.163.com/entry/cgi/ntesdoor?style=-1&df=mail163_letter&net=&language=-1&from=web&race=&iframe=1&product=mail163&funcid=loginone&passtype=1&allssl=true&url2=https://mail.163.com/errorpage/error163.htm"
       #设置代理,以防止本地IP被封
       self.proxyUrl = "http://202.106.16.36:3128"
       #初始化sid码
       self.sid = ""
       #第一次登陆所需要的请求头request headers,这些信息可以在ntesdoor日志request header中找到,copy过来就行
       self.loginHeaders = {
           'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,,image/webp,image/apng,*/*;q=0.8",
           'Accept-Language': "zh-CN,zh;q=0.9",
           'Connection': "keep-alive",
           'Host': "mail.163.com",
           'Referer': "http://mail.163.com/",
           'User-Agent':"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Mobile Safari/537.36"

       }
       #设置用户名和密码,填上自己的即可
       self.username = input('请输入邮箱地址:')
       self.pwd = input('请输入密码:')
       # self.username = input("邮箱地址:")
       # self.pwd = input("密码:")
       #post所包含的参数
       self.post = {
           'savelogin':"0",
           'url2':"http://mail.163.com/errorpage/error163.htm",
           'username':self.username,
           'password':self.pwd
       }
       # 对post编码转换
       self.postData = urllib.parse.urlencode(self.post).encode('utf8')
       # 使用http.cookiejar.CookieJar()创建CookieJar对象
       self.cjar = http.cookiejar.CookieJar()
       # 使用HTTPCookieProcessor创建cookie处理器,并以其为参数构建opener对象
       self.cookie = urllib.request.HTTPCookieProcessor(self.cjar)
       self.opener = urllib.request.build_opener(self.cookie)
       # 将opener安装为全局
       urllib.request.install_opener(self.opener)

   #模拟登陆并获取sid码
   def loginPage(self):
       try:
           #发出一个请求
           self.request = urllib.request.Request(self.loginUrl,self.postData,self.loginHeaders)
       except urllib.error.HTTPError as e:
           print(e.code)
           print(e.read().decode("utf8"))
       #得到响应
       self.response = urllib.request.urlopen(self.request)
       #需要将响应中的内容用read读取出来获得网页代码,网页编码为utf-8
       self.content = self.response.read().decode("utf8")
       #打印获得的网页代码
       # print(self.content)
       # 设定提取sid码的正则表达式
       self.sidpattern = re.compile('sid=(.*?)&', re.S)
       self.result = re.search(self.sidpattern, self.content)
       self.sid = self.result.group(1)
       # print('+'*50)
       # print("sid=", self.sid)

   #通过sid码获得邮箱收件箱信息
   def messageList(self):
       #重定向至收件箱的网址
       listUrl = 'http://mail.163.com/js6/s?sid=%s&func=mbox:listMessages&TopTabReaderShow=1&TopTabLofterShow=1&welcome_welcomemodule_mailrecom_click=1&LeftNavfolder1Click=1&mbox_folder_enter=1'%self.sid
       #新的请求头
       Headers = {
           'Accept': "text/javascript",
           'Accept-Language': "zh-CN,zh;q=0.9",
           'Connection': "keep-alive",
           'Host': "mail.163.com",
           'Referer': "https://mail.163.com/js6/main.jsp?sid=%suCFJZNnnRnInrsigqunnSrQXsvMMqctH&df=mail163_letter"%self.sid,
           'User-Agent':"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Mobile Safari/537.36"
       }
       #发出请求并获得响应
       request = urllib.request.Request(listUrl, headers=Headers)
       response = self.opener.open(request)
       #提取响应的页面内容,里面是收件箱的信息
       content = response.read().decode('utf-8')
       return content

   #获取邮件信息
   def getmail(self):
       messages = self.messageList()
       # print(messages)
       pattern = re.compile('from..(.*?),.*?to..(.*?),.*?subject..(.*?),.*?sentDate..(.*?),\n.*?receivedDate..(.*?),\n', re.S)
       mails = re.findall(pattern, messages)
       # print("+"*50)
       # 解析日期有问题, 月份需要手动加1, 遇12则变为13;
       list_final_end = []
       for i in range(0, len(mails)):
           list_new = mails[i]
           list_temp = list_new[0:3]
           list_temp_add = list_new[i][3][9:18]
           if list_temp_add[-1:] in range(0, 9):
               months = int(list_new[3][14:16])+1
               months = str(months)
               list_temp_add = [list_new[3][9:13]+months+list_new[3][17:19]]
           else:
               months = int(list_new[3][14:15])+1
               months = str(months)
               list_temp_add = [list_new[3][9:13]+'0'+months+list_new[3][16:18]]
           list_final = [list_temp + tuple(list_temp_add)]
           list_final_end += list_final
       # 打印邮件
       print('*' * 50)
       print('*' * 50)
       print('开始打印收件箱列表.')
       print('登录邮箱:', self.username)
       print('收件列表如下:')
       print('*' * 50)
       print('*' * 50)
       #对当前年份和月份的邮件进行筛选
       for mail in list_final_end:
           today_year = time.strftime("%Y", time.localtime())
           today_month = time.strftime("%m", time.localtime())
           mail_year = mail[3][0:4]
           mail_month = mail[3][4:6]
           if mail_year == today_year:
               if mail_month == today_month:
                   print('发送时间:', mail[3], '-', '主题:', mail[2], '-', '发件人:', mail[0])
                   print('-' * 50)
               else:
                   pass
           else:
               pass

mail=MAIL()
mail.loginPage()
mail.getmail()
os.system('pause')
上一篇下一篇

猜你喜欢

热点阅读