python爬⾍-搭建cookies池
写在前⾯
前段时间跟着静觅⼤神学习了⾃建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。这样⽅便扩展。
接下来我们创建⼀个存储模块类():
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.website = website
def name(self):
return"{type}:{website}".format(pe,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的名称。
另外,我们还需要⼀个导⼊数据的⽅法,便于批量导⼊⽤户名与密码。(听说淘宝上可以买账号,我没买,所以只导⼊了⼀个仅有的账号)
具体代码如下():
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即可。
这⾥我们对接的是马蜂窝⽹站,下⾯是⽣成模块的主要代码()
import json
from selenium import webdriver
from saver import RedisClient
from cookies.mafengcookies import MafengCookies
class CookiesGenerator(object):
def__init__(self,website='default'):
self.website = website
self.account_db = RedisClient('accounts',self.website)
self.init_browser()
def__del__(self):
self.close()
def init_browser(self):
self.option = webdriver.ChromeOptions()
self.option.add_argument('headless')
self.browser = webdriver.Chrome(executable_path='F:\BaiduNetdiskDownload\cookie_pool\chromedriver',chrome_options=self.option)
def new_cookies(self,username,password):
'''
新⽣成Cookies,⼦类需要重写
:param username: ⽤户名
:param password: 密码
:return:
'''
raise NotImplementedError
def process_cookies(self,cookies):
'''
处理Cookies
:param cookies:
:return:
'''
dict={}
dict={}
for cookie in cookies:
dict[cookie['name']]= cookie['value']
return dict
def run(self):
accounts_usernames = self.account_db.usernames()
cookies_usenames = kies_db.usernames()
#出没有Cookies的账号
for username in accounts_usernames:
if not username in cookies_usenames:
password = self.(username)
print('正在⽣成Cookies','账号',username,'密码','---')
result = w_cookies(username,password)
('status')==1:
cookies = self.process_('content'))
print('成功获取到Cookies',cookies)
kies_db.set(username,json.dumps(cookies)):
print('成功保存Cookies')
#密码错误,移除账号
('status')==2:
('content'))
if self.account_db.delete(username):
print('成功删除帐号')
else:
('content'))
else:
print('所有账号都已经成功获取Cookies')
def close(self):
try:
print('Closing Browser')
self.browser.close()
del self.browser
except TypeError:
print('Brower not opened')
class MafengCookiesGenerator(CookiesGenerator):
def__init__(self,website='mafeng'):
CookiesGenerator.__init__(self,website)
self.website = website
def new_cookies(self,username,password):
return MafengCookies(username,password,self.browser).main()
不过现在还需要加⼀个获取马蜂窝⽹站Cookies的类,并针对不同的情况返回不同的结果。具体代码如下所⽰():
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdrivermon.by import By
ptions as ex
import time
class MafengCookies():
def__init__(self,username,password,browser):
self.url ='passport.mafengwo/'
self.browser = browser
self.wait = WebDriverWait(self.browser,10)
self.username = username
self.password = password
def open(self):
'''
打开⽹页并输⼊⽤户名与密码
:return:
'''
(self.url)
username = self.wait.until(EC.presence_of_element_located((By.XPATH,'//form[@id="_j_login_form"]//i
nput[@name="passport"]')))        password = self.wait.until(EC.presence_of_element_located((By.XPATH,'//form[@id="_j_login_form"]//input[@name="password"]')))        submit = self.wait.until(EC.presence_of_element_located((By.XPATH,'//form[@id="_j_login_form"]//div[@class="submit-btn"]/button')))        username.send_keys(self.username)
password.send_keys(self.password)
time.sleep(2)
submit.click()
def password_error(self):
'''
判断密码是否错误
:return:
'''
try:
return bool(
WebDriverWait(self.browser,10).until(EC.presence_of_element_located((By.XPATH,'//div[@class="alert alert-danger"]'))) )
except ex.TimeoutException:
return False
def get_cookies(self):
'''
获取cookies
:return:
'''
return _cookies()
def login_successfully(self):
'''
判断是否登录成功
:return:
'''
try:
return bool(
selenium获取cookieWebDriverWait(self.browser,10).until(EC.presence_of_element_located((By.XPATH,'//div[@class="user-image"]'))) )
except ex.TimeoutException:
return False
def main(self):
self.open()
time.sleep(5)
if self.password_error():
return{
'status':2,
'content':'⽤户名或密码错误'
}
elif self.login_successfully():
cookies = _cookies()
return{
'status':1,
'content':cookies
}
else:
return{
'status':3,
'content':'登录失败'
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。