python 3.7 使用requests 爬取 163邮件列表 与 邮件内容详情

最近想使用网易邮箱批量注册几个网站小号,注册时需要获取邮箱收到的注册码,一个一个的点开邮件太麻烦,于是就产生了写这个脚本的想法,中间也遇到一些问题,会在文章中详细的解说。

本文将使用 requests 库来实现需求,当然也可以使用 urllibimaplibselenium

  • urllib 实现过程跟requests相近;
  • imaplib 应用于开启了 IMAP/SMTP服务 的场景;
  • selenium多应用于自动化测试中,结合浏览器使用的;

接下来要实现我的小目标,首先先分解下功能:

  • 1.实现163邮箱自动登录
  • 2.获取邮件列表
  • 3.找到收到验证码的邮件(由于某些原因,本文忽略此步)
  • 4.抓取邮件详细内容

先提前说一下,实现的过程遇到的一些问题:

  • SSL校验问题
  • 抓取邮件详细内容时,一直提示登录超时

以上问题都已解决,接下来细说一下实现的过程

一、实现163邮箱自动登录

思路:使用账号密码,获取 sid 和 cookie

登录部分没有什么难点,主要是url找对,就没问题了,代码如下:

import requests
import re
import urllib3

#忽略证书警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

class MAIL163:
    def __init__(self, username, password):
        self.session = requests.Session()

        self.username = username
        self.password = password
        self.sid = None

    def login(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"
        headers = {
            'Referer': "https://mail.163.com/",
            'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Safari/605.1.15"
        }

        postData = {
            'savelogin': "0",
            'url2': "http://mail.163.com/errorpage/error163.htm",
            'username': self.username,
            'password': self.password
        }

        response = self.session.post(loginUrl, headers=headers, data=postData, verify=False)
        #提取sid,获取邮件信息需要使用它
        pattern = re.compile(r'sid=(.*?)&', re.S)
        self.sid = re.search(pattern, response.text).group(1)

二、获取邮件列表

思路:利用登录获取的 sid 和 cookie ,请求数据

获取列表部分,写的时候遇到了点问题,主要是获取mail的各种信息,当时用 charles抓包时,返回的数据是json格式的,但是用requests请求,得到响应结果,进行解析json时,提示格式错误:

Expecting property name enclosed in double quotes: line 1 column 2(char 1)

后来找到了解决办法:使用demjson的包来处理,参照文章,但是最后我还是选择了使用正则匹配(没有原因),代码如下:


    def messageList(self):
        listUrl = 'https://mail.163.com/js6/s?sid=%s&func=mbox:listMessages' % 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=%s&df=mail163_letter" % self.sid,
            'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Safari/605.1.15"
        }

        response = self.session.post(listUrl, headers=Headers, verify=False)

        pattern = re.compile(
            "id..'(.*?)',.*?from..'(.*?)',.*?to..'(.*?)',.*?subject..'(.*?)',.*?sentDate..(.*?),\n.*?receivedDate..(.*?),.*?hmid..(.*?),\n",
            re.S)
        mails = re.findall(pattern, response.text)
        for mail in mails:
            mid = mail[0]
            print('-' * 45)
            print('mid:', mid)
            print('发件人:', mail[1], '主题:', mail[3], '发送时间:', mail[4])
            print('收件人:', mail[2], u'接收时间:', mail[5])

三、抓取邮件详细内容

思路:利用登录获取的 sid 和 cookie、邮件列表获取的 mid ,来请求数据

这部分是卡住我的关键点,headers改来改去的,始终获取不到邮件内容,查阅了一些文章,说是sid失效的原因,但是我用charles抓包,sid从没有失效过,我猜想应该是哪里少了参数,于是仔细对比charles请求的headers、cookie、表单等一切信息,发现需要在原 cookie中新增sid内容,对应的字段名为‘Coremail.sid’,具体代码如下:


 def message(self, mid):
        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=%s&df=mail163_letter" % self.sid,
            'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Safari/605.1.15"
        }
        
        #cookie加上这个,才能获取邮件详情
        cookie = {
            'Coremail.sid': self.sid,
        }

        url = 'https://mail.163.com/js6/read/readhtml.jsp?mid=%s&userType=ud&font=15&color=064977' % mid
        requests.utils.add_dict_to_cookiejar(self.session.cookies, cookie)
        response = self.session.get(url, headers=Headers, verify=False)

        print('邮件详情 =====>')
        print(response.text)

四、最后一步:将所有功能串联起来

email_163.py整体的代码如下:

#!/usr/bin/env
# -*- coding:utf-8 -*-
import requests
import re
import json
import urllib3

# 忽略证书警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

class MAIL163:
    def __init__(self, username, password):
        self.session = requests.Session()

        self.username = username
        self.password = password
        self.sid = None

    def login(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"
        headers = {
            'Referer': "https://mail.163.com/",
            'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Safari/605.1.15"
        }

        postData = {
            'savelogin': "0",
            'url2': "http://mail.163.com/errorpage/error163.htm",
            'username': self.username,
            'password': self.password
        }

        response = self.session.post(loginUrl, headers=headers, data=postData, verify=False)
        #提取sid,获取邮件信息需要使用它
        pattern = re.compile(r'sid=(.*?)&', re.S)
        self.sid = re.search(pattern, response.text).group(1)

    # 通过sid码获得邮箱收件箱信息
    def messageList(self):
        listUrl = 'https://mail.163.com/js6/s?sid=%s&func=mbox:listMessages' % 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=%s&df=mail163_letter" % self.sid,
            'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Safari/605.1.15"
        }

        response = self.session.post(listUrl, headers=Headers, verify=False)

        pattern = re.compile(
            "id..'(.*?)',.*?from..'(.*?)',.*?to..'(.*?)',.*?subject..'(.*?)',.*?sentDate..(.*?),\n.*?receivedDate..(.*?),.*?hmid..(.*?),\n",
            re.S)
        mails = re.findall(pattern, response.text)

        for mail in mails:
            mid = mail[0]
            print('-' * 45)
            print('id:', mid)
            print('发件人:', mail[1], '主题:', mail[3], '发送时间:', mail[4])
            print('收件人:', mail[2], u'接收时间:', mail[5])
            self.message(mid)

    def message(self, mid):
        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=%s&df=mail163_letter" % self.sid,
            'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Safari/605.1.15"
        }

        #cookie加上这个,才能获取邮件详情
        cookie = {
            'Coremail.sid': self.sid,
        }

        url = 'https://mail.163.com/js6/read/readhtml.jsp?mid=%s&userType=ud&font=15&color=064977' % mid
        requests.utils.add_dict_to_cookiejar(self.session.cookies, cookie)
        response = self.session.get(url, headers=Headers, verify=False)

        print('邮件详情 =====>')
        print(response.text)


if __name__ == "__main__":
    mail = MAIL163('*****@163.com', '****')
    mail.login()
    mail.messageList()

参考文章:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 155,770评论 4 358
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,116评论 1 286
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 105,656评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,372评论 0 201
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,704评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,166评论 1 204
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,535评论 2 306
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,259评论 0 193
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,882评论 1 236
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,218评论 2 239
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,760评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,126评论 2 249
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,667评论 3 228
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,935评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,644评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,171评论 2 265
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,119评论 2 258