1、配置邮箱账号 163为例
settings.py
# 邮箱配置 MAIL_HOST = "smtp.163.com" MAIL_FROM = "xxx@163.com" MAIL_USER = "xxx@163.com" MAIL_PASS = "xxx" # 授权码 MAIL_PORT = 25
2、发送邮件的代码
# -*- coding: utf-8 -*-
import scrapy
from scrapy import cmdline
from scrapy.mail import MailSender
class SendEmailSpider(scrapy.Spider):
name = 'send_email'
start_urls = ['https://www.baidu.com/';]
def parse(self, response):
# 方式一:读取配置文件中的配置
# debug参数为True 不会发送邮件,仅仅打印日志
mailer = MailSender(
smtphost=self.settings["MAIL_HOST"],
mailfrom=self.settings["MAIL_FROM"],
smtpuser=self.settings["MAIL_USER"],
smtppass=self.settings["MAIL_PASS"],
smtpport=self.settings["MAIL_PORT"]
)
# 方式二:直接传入settings 对象
mailer = MailSender.from_settings(self.settings)
# 发送邮件
return mailer.send(
to=["xxx@qq.com"],
subject="这是邮件标题",
body="这是邮件内容"
)
if name == '__main__':
cmdline.execute("scrapy crawl send_email".split())
问题
1、问题一
以上代码如果不加return
, 可以正常发送邮件
mailer.send(
to=["xxx@qq.com"],
subject="这是邮件标题",
body="这是邮件内容"
)
不过会报错
builtins.AttributeError: 'NoneType' object has no attribute 'bio_read'
2、问题二
如果按照文档的写法直接不传参数实例化MailSender
mailer = MailSender()
会报错
Unable to send mail: To=['xxx@qq.com'] Cc=[] Subject="这是邮件标题" Attachs=0-
Connection was refused by other side: 61: Connection refused.
原因是MailSender
的实例化参数是固定的默认值,并没有读取settings.py文件中设定的值,坑~~
构造函数源码如下
class MailSender(object):
def __init__(self, smtphost='localhost', mailfrom='scrapy@localhost',
smtpuser=None, smtppass=None, smtpport=25,
smtptls=False, smtpssl=False, debug=False):
self.smtphost = smtphost
self.smtpport = smtpport
self.smtpuser = _to_bytes_or_none(smtpuser)
self.smtppass = _to_bytes_or_none(smtppass)
self.smtptls = smtptls
self.smtpssl = smtpssl
self.mailfrom = mailfrom
self.debug = debug
如果采用此方式实例化MailSender
需要采用方式一手动读取配置
吐槽:搞不懂scrapy作者为啥要设置完全没有用的默认值, 也不报错,坑了一波人
3、问题三
如果按照文档的写法
mailer = MailSender.from_settings(settings)
直接就会报错,都没有定义
NameError: name 'settings' is not defined
我的第一感觉是把项目的settings.py
导入传进去
import settings
mailer = MailSender.from_settings(settings)
然后又报错了
TypeError: 'module' object is not subscriptable
查看文档参数说明才知道要传一个settings
对象
settings (scrapy.settings.Settings object)
所以需要按照方式二的形式,才能正确获取setting对象
吐槽:动态语言的函数定义并没有严格要求参数类型,没有把具体的参数类型写清楚,不看文档完全不知道传什么参数
参考
</div>