前言
最近在做一项从邮箱拿取数据进行处理的任务,由于数据量过大并且数据是邮件中的内容,所以想实现自动化拿取数据,避免搬运工的命运!
参考项目
整体思路
由于对爬虫的相关知识没有太多的学习基础,这里参考了不少的相关文章。1、2讲的比较详细,可以用来理解我们的需求,补充需求的理论知识。通过查阅各种文章可以看出,我们要实现爬取邮箱,需要以下步骤:
- 从网页或者Fiddler拿到所需数据,如header、cookie、postdata等
- 编写代码发送post请求抓取数据获取sid码
- 通过cookie与sid组合登录邮箱,爬取收件箱目录及地址
- 通过收件箱目录及地址爬取邮件相关内容
- 正则匹配输出到本地,Finish
下面给出两种方法,来实现邮箱数据的爬取,由于基础有限,方法注重实用性
基于urllib实现非自动爬取163邮箱
抓取网页信息
首先还是抓取网页信息。以Chorme为例:
打开163邮箱网站进行检查,然后登录后查看ntesdoor,在Headers里,可以查找到cookie、URL和Header
将cookie header 和url 拿取出
headers = {
'content-length': '447',
'cache-control': 'max-age=0',
'sec-ch-ua': '"Chromium";v="104", " Not A;Brand";v="99", "Google Chrome";v="104"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
'upgrade-insecure-requests': '1',
'origin': 'https://mail.163.com',
'content-type': 'application/x-www-form-urlencoded',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
'accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'navigate',
'sec-fetch-dest': 'iframe',
'referer': 'https://mail.163.com/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
}
cookie = {
#主要是拿出MAIL_SESS
'NTES_SESS':"",
}
url = 'https://mail.163.com/entry/cgi/ntesdoor?'
然后利用request里的session,使用post请求进行访问,通过其response 获得sid 。requests库的session会话对象可以跨请求保持某些参数,使用session成功的登录了某个网站,则在再次使用该session对象求求该网站的其他网页都会默认使用该session之前使用的cookie等参数,则进行登录收件箱时不需要再爬取cookie 和 sid.
登录这个网站,需要postdata,即负载Payload内的数据:
data = {
'style': '-1',
'df': 'mail163_letter',
'allssl': 'true',
'net': '',
'deviceId': '**********',#需要放置自己的ID
'sdid': '8606104245******8',#需要放置自己的SDID
'language': '-1',
'from': 'web',
'race': '',
'iframe': '1',
'url2': 'https://mail.163.com/errorpage/error163.htm',
'product': 'mail163'
}
接下来就可以利用SESSION爬取数据了
response = self.session.post(url, headers=headers,cookies=cookie,
json=json.dumps(data, ensure_ascii=False), verify=False)
再通过正则表达式提取出sid,所以需要准备的数据整整齐齐QAQ!
获取收件箱列表内容
重新打开检查框,点击收信按钮:
可以看到检查按钮,这个listMessages即为获取收件箱列表信息的url链接,我们不需要cookie,sid开始起了作用!!!另外负载data 发生了变换,这个需要继续改变。
继续写:
listUrl = 'https://mail.163.com/js6/s?sid=%s&func=mbox:listMessages' % self.sid
data = {
'var' :'<?xml version="1.0"?><object><int name="fid">1</int><string name="order">date</string><boolean name="desc">true</boolean><int name="limit">20</int><int name="start">0</int><boolean name="skipLockedFolders">false</boolean><string name="topFlag">top</string><boolean name="returnTag">true</boolean><boolean name="returnTotal">true</boolean><string name="mrcid">84ab7da8*********</string></object>'
}
response = self.session.post(listUrl, headers=Headers,
json=json.dumps(data, ensure_ascii=False),verify=False)
这里已经成功80%了,接下来就可以进行内容爬取了!
获取信件
再次重新打开网页检查,可以看到readhtml页面,mid即为上面的圈出的ID,通过遍历ID即可获得邮件内容,通过正则匹配,即可完成整个爬取过程。
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)
pattern = re.compile(
'<pre>(.*?)</pre>',
re.S)
mail_data =[]
mail_data = re.findall(pattern, response.text)
try:
if len(mail_data[0].split('\r\n')) >10:
fout = open(mailname+'.txt', mode='w', encoding="utf-8")
fout.writelines(mail_data)
print(f"完成{mailname}")
except Exception as e:
pass
结束!
338为邮件总数,后面为爬取的邮件