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

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

作者: 花___ | 来源:发表于2020-02-13 20:22 被阅读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')
    

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/foykfhtx.html