写在前面
前段时间跟着静觅大神学习了自建ip代理池,
但是很多情况下,页面的某些信息需要登录才能查看。
所以,今天又和大神学习了cookies池的搭建。
整体思路
Cookies池的架构和代理池类似,同样是4个核心模块(存储模块、生成模块、检测模块和接口模块):
- 存储模块,负责存储每个账号的用户名、密码以及每个账号对应的Cookies信息,同时还需要提供一些方法来实现方便的存取操作。
- 生成模块,负责生成新的Cookies。此模块会从存储模块逐个拿取账号的用户名和密码,然后模拟登录目标页面,判断登录成功,就将Cookies返回并交给存储模块存储。
- 检测模块,定时检测数据库中的Cookies。在这里我们需要设置一个检测链接,不同的站点检测链接不同,检测模块会逐个拿取账号对应的Cookies去请求链接,如果返回的状态是有效的,那么此Cookies没有失效,否则Cookies失效并移除。接下来等待生成模块重新生成即可。
- 接口模块,需要用API来提供对外服务的接口。由于可用的Cookies可能有多个,我们可以随机返回Cookies的接口,这样保证每个Cookies都有可能被取到。Cookies越多,每个Cookies被取到的概率就会越小,从而减少被封号的风险。
以上就是Cookies池的框架,下面我们一一来实现各个模块吧。
存储模块
需要存储的内容包括账号信息与Cookies信息。
账号由用户名和密码两部分组成,我们可以存成用户名和密码的映射。Cookies可以存成JSON字符串,但是我们后面得需要根据账号来生成Cookies。生成的时候我们需要知道哪些账号已经生成了Cookies,哪些没有生成,所以需要同时保存该Cookies对应的用户名信息,其实也是用户名和Cookies的映射。
这里就是两组映射,Redis的Hash有天然的优势,所以这里我们就建立两个Hash。Hash的Key就是账号,Value对应着密码或者Cookies。
由于Cookies池需要可扩展,存储的账号和Cookies可能不止一个网站,所以这里Hash的名称可以做二级分类。以马蜂窝为例,存放账号的Hash名称可以为accounts:mafeng,存放Cookies的Hash名称为cookies:mafeng。这样方便扩展。
接下来我们创建一个存储模块类(saver.py):
import random
import redis
REDIS_HOST = 'localhost'
REDIS_PORT = 6379
REDIS_PASSWORD = None
class RedisClient(object):
def __init__(self,type,website,host=REDIS_HOST,port=REDIS_PORT,password=REDIS_PASSWORD):
self.db = redis.StrictRedis(host=host,port=port,password=password,decode_responses=True)
self.type = type
self.website = website
def name(self):
return "{type}:{website}".format(type=self.type,website=self.website)
def set(self,username,value):
'''
设置键值对
:param username: 用户名
:param value: 密码或cookies
:return:
'''
return self.db.hset(self.name(),username,value)
def get(self,username):
'''
根据键名获取键值
:param username: 用户名
:return:
'''
return self.db.hget(self.name(),username)
def delete(self,username):
'''
根据键名删除键值对
:param username: 用户名
:return: 删除结果
'''
return self.db.hdel(self.name(),username)
def count(self):
'''
获取数目
:return:数目
'''
return self.db.hlen(self.name())
def random(self):
'''
随机获得键值,用户随机cookies获取
:return: 随机Cookies
'''
return random.choice(self.db.hvals(self.name()))
def usernames(self):
'''
获取所有账户信息
:return: 所有用户名
'''
return self.db.hkeys(self.name())
def all(self):
'''
获取所有键值对
:return: 用户名和密码或cookies的映射表
'''
return self.db.hgetall(self.name())
这里要注意的是,name()方法拼接了type和website,组成Hash的名称。
另外,我们还需要一个导入数据的方法,便于批量导入用户名与密码。
(听说淘宝上可以买账号,我没买,所以只导入了一个仅有的账号)
具体代码如下(importer.py):
from saver import RedisClient
conn = RedisClient('accounts', 'mafeng')
def set(account, sep='----'):
username, password = account.split(sep)
result = conn.set(username, password)
print('账号', username, '密码', password)
print('录入成功' if result else '录入失败')
def scan():
print('请输入账号密码组, 输入exit退出读入')
while True:
account = input()
if account == 'exit':
break
set(account)
if __name__ == '__main__':
scan()
生成模块
生成模块负责获取各个账号信息并模拟登录,随后生成Cookies并保存。我们首先获取两个Hash的信息,看看账户的Hash比Cookies的多了哪些还没有生成Cookies的账号,然后将剩余的账号遍历,再去生成Cookies即可。
这里我们对接的是马蜂窝网站,下面是生成模块的主要代码(<