背景介绍:之前写过通过通过scrapy的扩展发送邮件,在爬虫关闭的时候发送邮件。那个时候有个问题就是MailSender对象需要return出去。这次需要在中间件中发送邮件,但是中间件中不能随便使用return了。

import json
import random
import scrapy
from scrapy.http import Response
from scrapy.mail import MailSender
from scrapy.exceptions import IgnoreRequest from order_spider.databases.connections import redis_db class LoginTokenMiddleware(object): def __init__(self,mailer):
self.mailer = mailer @classmethod
def from_crawler(cls, crawler):
smtphost = crawler.settings.get('MAIL_HOST') # 发送邮件的服务器
mail_port = crawler.settings.get('MAIL_PORT') # 邮件发送者
mailfrom = crawler.settings.get('MAIL_USER') # 邮件发送者
smtppass = crawler.settings.get('MAIL_PASS') # 发送邮箱的密码不是你注册时的密码,而是授权码!!!切记!
mailer = MailSender(smtphost, mailfrom, mailfrom, smtppass, smtpport=mail_port)
return cls(mailer) def _send_mail(self,subject,body):
return self.mailer.send(to={'feijun.zheng@huijie-inc.com'}, subject=subject, body=body) def process_request(self, request:scrapy.Request, spider):
#从数据库获取所有的用户session
tokens = redis_db.hgetall("order:xxx")
users = []
for k,v in tokens.items():
#如果用户value有0,代表过期
if "0" not in v:
users.append(k)
if not users:
try:
#通过end_signal判断爬虫是否继续执行
if spider.end_signal:
raise IgnoreRequest
# 设置为True,避免重复发送邮件
spider.end_signal = True
spider.logger.warning("session全部过期请重新添加")
body = 'xxxxx全部过期'
subject = '没有可用的账号,请重新添加'
#mail添加回调,避免出现`exceptions.AttributeError: 'NoneType' object has no attribute 'bio_read'`
self._send_mail(body,subject).addCallback(lambda x: x)
except Exception as e:
spider.logger.exception(e)
finally:
# 没有可用账号,关闭爬虫
spider.crawler.engine.close_spider(spider, "爬虫关闭")
# 忽略后续的请求
raise IgnoreRequest session_id = random.choice(users)
request.cookies = {"JSESSIONID":session_id}
return None def process_response(self, request, response:Response, spider):
res = json.loads(response.text) if res['code'] != 1:
session_id = request.cookies['JSESSIONID']
user = redis_db.hmget("order:xxxx",session_id)[0]
redis_db.hset("order:xxxx",session_id,user+'_0') spider.logger.info("登录失败,失败原因:%s" %(res['msg']))
body = 'session[%s] 可能已过期\n 失败原因%s'%(session_id,res['msg'])
subject = '账号登录失败提醒'
self._send_mail(body,subject).addCallback(lambda x: x)
return response

推荐还是在扩展中使用发送邮件的功能,可以参考:

scrapy通过扩展发送邮件

还有一个小问题就是:阿里云上默认不能使用25端口,所以你需要使用456端口进行发送,456端口需要使用SSL,需要在原来的基础上做个小修改:

mailer = MailSender(mail_host, mail_user, mail_user, mail_pass, mail_port, smtptls=True, smtpssl=True)

具体参数参考官方文档:

scrapy文档

scrapy中间件中发送邮件的更多相关文章

  1. scrapy中间件中使用selenium切换ip

    scrapy抓取一些需要js加载页面时一般要么是通过接口直接获取数据,要么是js加载,但是我通过selenium也可以获取动态页面 但是有个问题,容易给反爬,因为在scrapy中间件mid中使用sel ...

  2. Python爬虫从入门到放弃(十七)之 Scrapy框架中Download Middleware用法

    这篇文章中写了常用的下载中间件的用法和例子.Downloader Middleware处理的过程主要在调度器发送requests请求的时候以及网页将response结果返回给spiders的时候,所以 ...

  3. Scrapy中间件user-agent和ip代理使用

    一.定义实现随机User-Agent的下载中间件 1.在middlewares.py中完善代码 import random from Tencent.settings import USER_AGEN ...

  4. Python爬虫从入门到放弃 之 Scrapy框架中Download Middleware用法

    这篇文章中写了常用的下载中间件的用法和例子.Downloader Middleware处理的过程主要在调度器发送requests请求的时候以及网页将response结果返回给spiders的时候,所以 ...

  5. scrapy框架中Download Middleware用法

    scrapy框架中Download Middleware用法   Downloader Middleware处理的过程主要在调度器发送requests请求的时候以及网页将response结果返回给sp ...

  6. scrapy——中间件UserAgent代理

    pip install fake-useragent 使用说明:from fake_useragent import UserAgent# 实例化一个UserAgent对象ua = UserAgent ...

  7. scrapy中间件之下载中间件使用(网易新闻爬取)

    scrapy项目中的middlewarse.py中间件 爬虫中间件:目前先不介绍 下载中间件(需要在settings.py中开启) (1)请求处理函数:process_request(self, re ...

  8. Python之爬虫(十九) Scrapy框架中Download Middleware用法

    这篇文章中写了常用的下载中间件的用法和例子.Downloader Middleware处理的过程主要在调度器发送requests请求的时候以及网页将response结果返回给spiders的时候,所以 ...

  9. Node.js连接Mysql,并把连接集成进Express中间件中

    引言 在node.js连接mysql的过程,我们通常有两种连接方法,普通连接和连接池. 这两种方法较为常见,当我们使用express框架时还会选择使用中间express-myconnection,可以 ...

随机推荐

  1. 如何让SQL语句不执行默认排序,而是按照in语句的顺序返回结果

    Oracle: ')order by instr('111,222,333,444,555,666',order_id); Mysql: ') order by instr(',111,222,333 ...

  2. G++命令

    gcc and g++分别是gnu的c & c++编译器. 从源代码到可执行文件的四步 gcc/g++在执行编译工作的时候,总共需要4步 1.预处理,生成.i的文件,用到预处理器cpp.这一步 ...

  3. Zifencei扩展

    fence 指令对外部可见的访存请求,如设备 I / O 访问,内存访问等进行串行化.外部可见是指对处理器的其他核心.线程,外部设备或协处理器可见. fence.i 指令同步指令和数据流.在执行 fe ...

  4. android studio学习---模板

    Android Studio还为开发人员提供多种模板选项,从而大大提升开发速度.这些模板能自动创建Activity以及必要的XML文件.大家还可以利用这些模板创建出较为基础的Android应用程序,并 ...

  5. 01篇ELK日志系统——升级版集群之elasticsearch集群的搭建

    [ 前言:以前搭了个简单的ELK日志系统,以我个人的感觉来说,ELK日志系统还是非常好用的.以前没有弄这个ELK日志系统的时候,线上的项目出了bug,报错了,要定位错误是什么,错误出现在哪个java代 ...

  6. swagger页面详细讲解

  7. CDH报错:PersistenceException: [PersistenceUnit: cmf.server] Unable to build EntityManagerFactory

    1.在启动CDH中master的服务cloudera-scm-server start并立刻挂掉了,提示如下错误 org.springframework.beans.factory.BeanCreat ...

  8. Java--8--新特性--串并行流与ForkJoin框架

    并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流.穿行流则相反,并行流的底层其实就是ForkJoin框架的一个实现. 那么先了解一下ForkJoin框架吧. Fork/Join ...

  9. windows开启PostgreSQL数据库远程访问

    1.在PostgreSQL安装目录下data文件夹,打开pg_hba.conf文件,新增允许访问的ip 2.打开postgresql.conf,将listen_addresses = 'localho ...

  10. The Preliminary Contest for ICPC Asia Shenyang 2019 H. Texas hold'em Poker

    题目链接:https://nanti.jisuanke.com/t/41408 题目意思很简单,就是个模拟过程. #include <iostream> #include <cstr ...