背景:利用代理池爬取微信公众号文章并保存
架构:
巨坑:实例的名不可于类的名重复。
第一:请求及请求队列
1、为什么要创建weixinrequest()?
因为Sogou微信搜索反爬虫能力强,response.status_code容易出现302,也就是需要输入验证码。当然解决这个问题有两个途径,一个是调用验证码自动识别,另一个是将该302连接重新放回请求队列,更好代理继续。
继承requests库的request类,创建一个weixinququest类,主要添加额为四个属性,callback、need_proxy,failtime,timeout。callback实现每个连接的回调对应方法解析,needproxy是否需要代理,failtime,允许失败的最大次数,已经连接最大响应时间。
from requests import Request
from config import *
class weixinrequest(Request):
"""
super().__init__(a,b,c)继承类时,当子类重写init方法,遇到和父类同样的属性。直接显示引用属性
(a,b,c)中的abc为子类init()中传入的参数,且传入的参数要与要父类中属性先后顺序一致。
"""
def __init__(self,url,callback,method='GET',headers=None,need_proxy=False,fail_time=0,timeout=TIMEOUT):
super(weixinrequest,self).__init__(method,url,headers)#显示调用指定父类init这个三个属性,其他父类属性则相当于丢弃!!这三个属性,要和源码中属性出现的顺序对应
self.callback=callback
self.need_proxy=need_proxy
self.fail_time=fail_time
self.timeout=timeout
2、请求怎么保存?
每一个链接对应一个请求,我们要实现请求的放回,所有需要一个存储结构保存请求,选用了redis数据库中的列表形式来实现。基于redist列表创建一个redisqueue类,此外,由于redis的列表只允许插入字符性数据,所有需要把请求【weixinrequest实例】序列化,应用到pickle的两个函数,dumps序列化;取出后loads反序列化。
该类主要实现的三个方法:a、请求添加到队列:db.rpush(redis_key,dumps(wexrequest)),如果对应的列表redis_key不存 在,则新建一个列表
b、请求队列取出:loads(db.lpop(redis_key))从列表【redis_key】左侧取出一个队列,并反序列化
c、请求队列是否为空:db.llen(redis_key)
class RedisQueue